Skip to content

Commit 1a5e081

Browse files
committed
Add Match.buildTag() method as a shorthand for Autolinker.getTagBuilder().build( match ). Fixes #143
1 parent 733c05b commit 1a5e081

File tree

21 files changed

+280
-208
lines changed

21 files changed

+280
-208
lines changed

src/AnchorTagBuilder.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
* @class Autolinker.AnchorTagBuilder
66
* @extends Object
77
*
8-
* Builds anchor (<a>) tags for the Autolinker utility when a match is found.
8+
* Builds anchor (<a>) tags for the Autolinker utility when a match is
9+
* found.
910
*
1011
* Normally this class is instantiated, configured, and used internally by an
1112
* {@link Autolinker} instance, but may actually be retrieved in a {@link Autolinker#replaceFn replaceFn}

src/Autolinker.js

Lines changed: 36 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,33 @@ Autolinker.prototype = {
422422
},
423423

424424

425+
/**
426+
* After we have found all matches, we need to remove subsequent matches
427+
* that overlap with a previous match. This can happen for instance with
428+
* URLs, where the url 'google.com/#link' would match '#link' as a hashtag.
429+
*
430+
* @private
431+
* @param {Autolinker.match.Match[]} matches
432+
* @return {Autolinker.match.Match[]}
433+
*/
434+
compactMatches : function( matches ) {
435+
// First, the matches need to be sorted in order of offset
436+
matches.sort( function( a, b ) { return a.getOffset() - b.getOffset(); } );
437+
438+
for( var i = 0; i < matches.length - 1; i++ ) {
439+
var match = matches[ i ],
440+
endIdx = match.getOffset() + match.getMatchedText().length;
441+
442+
// Remove subsequent matches that overlap with the current match
443+
while( i + 1 < matches.length && matches[ i + 1 ].getOffset() <= endIdx ) {
444+
matches.splice( i + 1, 1 );
445+
}
446+
}
447+
448+
return matches;
449+
},
450+
451+
425452
/**
426453
* Removes matches for matchers that were turned off in the options. For
427454
* example, if {@link #hashtag hashtags} were not to be matched, we'll
@@ -454,33 +481,6 @@ Autolinker.prototype = {
454481
},
455482

456483

457-
/**
458-
* After we have found all matches, we need to remove subsequent matches
459-
* that overlap with a previous match. This can happen for instance with
460-
* URLs, where the url 'google.com/#link' would match '#link' as a hashtag.
461-
*
462-
* @private
463-
* @param {Autolinker.match.Match[]} matches
464-
* @return {Autolinker.match.Match[]}
465-
*/
466-
compactMatches : function( matches ) {
467-
// First, the matches need to be sorted in order of offset
468-
matches.sort( function( a, b ) { return a.getOffset() - b.getOffset(); } );
469-
470-
for( var i = 0; i < matches.length - 1; i++ ) {
471-
var match = matches[ i ],
472-
endIdx = match.getOffset() + match.getMatchedText().length;
473-
474-
// Remove subsequent matches that overlap with the current match
475-
while( i + 1 < matches.length && matches[ i + 1 ].getOffset() <= endIdx ) {
476-
matches.splice( i + 1, 1 );
477-
}
478-
}
479-
480-
return matches;
481-
},
482-
483-
484484
/**
485485
* Parses the input `text` looking for URLs, email addresses, phone
486486
* numbers, username handles, and hashtags (depending on the configuration
@@ -594,8 +594,7 @@ Autolinker.prototype = {
594594

595595
} else { // replaceFnResult === true, or no/unknown return value from function
596596
// Perform Autolinker's default anchor tag generation
597-
var tagBuilder = this.getTagBuilder(),
598-
anchorTag = tagBuilder.build( match ); // returns an Autolinker.HtmlTag instance
597+
var anchorTag = match.buildTag(); // returns an Autolinker.HtmlTag instance
599598

600599
return anchorTag.toAnchorString();
601600
}
@@ -629,13 +628,15 @@ Autolinker.prototype = {
629628
*/
630629
getMatchers : function() {
631630
if( !this.matchers ) {
632-
var matchersNs = Autolinker.matcher;
631+
var matchersNs = Autolinker.matcher,
632+
tagBuilder = this.getTagBuilder();
633+
633634
var matchers = [
634-
new matchersNs.Hashtag( { serviceName: this.hashtag } ),
635-
new matchersNs.Email(),
636-
new matchersNs.Phone(),
637-
new matchersNs.Twitter(),
638-
new matchersNs.Url( { stripPrefix: this.stripPrefix } )
635+
new matchersNs.Hashtag( { tagBuilder: tagBuilder, serviceName: this.hashtag } ),
636+
new matchersNs.Email( { tagBuilder: tagBuilder } ),
637+
new matchersNs.Phone( { tagBuilder: tagBuilder } ),
638+
new matchersNs.Twitter( { tagBuilder: tagBuilder } ),
639+
new matchersNs.Url( { tagBuilder: tagBuilder, stripPrefix: this.stripPrefix } )
639640
];
640641

641642
return ( this.matchers = matchers );

src/match/Email.js

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,25 @@
1010
Autolinker.match.Email = Autolinker.Util.extend( Autolinker.match.Match, {
1111

1212
/**
13-
* @protected
14-
* @property {String} email (required)
13+
* @cfg {String} email (required)
1514
*
1615
* The email address that was matched.
1716
*/
1817

1918

2019
/**
2120
* @constructor
22-
* @param {String} matchedText The original text that was matched.
23-
* @param {Number} offset The offset of where the match was made in the
24-
* input string.
25-
* @param {String} email The email address that was matched.
21+
* @param {Object} cfg The configuration properties for the Match
22+
* instance, specified in an Object (map).
2623
*/
27-
constructor : function( matchedText, offset, email ) {
28-
Autolinker.match.Match.prototype.constructor.call( this, matchedText, offset );
24+
constructor : function( cfg ) {
25+
Autolinker.match.Match.prototype.constructor.call( this, cfg );
2926

3027
// @if DEBUG
31-
if( !email ) throw new Error( '`email` arg required' );
28+
if( !cfg.email ) throw new Error( '`email` cfg required' );
3229
// @endif
3330

34-
this.email = email;
31+
this.email = cfg.email;
3532
},
3633

3734

src/match/Hashtag.js

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,40 +12,34 @@
1212
Autolinker.match.Hashtag = Autolinker.Util.extend( Autolinker.match.Match, {
1313

1414
/**
15-
* @protected
16-
* @property {String} serviceName
15+
* @cfg {String} serviceName
1716
*
1817
* The service to point hashtag matches to. See {@link Autolinker#hashtag}
1918
* for available values.
2019
*/
2120

2221
/**
23-
* @protected
24-
* @property {String} hashtag
22+
* @cfg {String} hashtag (required)
2523
*
2624
* The Hashtag that was matched, without the '#'.
2725
*/
2826

2927

3028
/**
3129
* @constructor
32-
* @param {String} matchedText The original text that was matched.
33-
* @param {Number} offset The offset of where the match was made in the
34-
* input string.
35-
* @param {String} serviceName The service to point hashtag matches to. See
36-
* {@link Autolinker#hashtag} for available values.
37-
* @param {String} hashtag The Hashtag that was matched, without the '#'.
30+
* @param {Object} cfg The configuration properties for the Match
31+
* instance, specified in an Object (map).
3832
*/
39-
constructor : function( matchedText, offset, serviceName, hashtag ) {
40-
Autolinker.match.Match.prototype.constructor.call( this, matchedText, offset );
33+
constructor : function( cfg ) {
34+
Autolinker.match.Match.prototype.constructor.call( this, cfg );
4135

4236
// @if DEBUG
43-
// TODO: if( !serviceName ) throw new Error( '`serviceName` arg required' );
44-
if( !hashtag ) throw new Error( '`hashtag` arg required' );
37+
// TODO: if( !serviceName ) throw new Error( '`serviceName` cfg required' );
38+
if( !cfg.hashtag ) throw new Error( '`hashtag` cfg required' );
4539
// @endif
4640

47-
this.serviceName = serviceName;
48-
this.hashtag = hashtag;
41+
this.serviceName = cfg.serviceName;
42+
this.hashtag = cfg.hashtag;
4943
},
5044

5145

src/match/Match.js

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,30 +33,40 @@
3333
Autolinker.match.Match = Autolinker.Util.extend( Object, {
3434

3535
/**
36-
* @protected
37-
* @property {String} matchedText
36+
* @cfg {Autolinker.AnchorTagBuilder} tagBuilder (required)
37+
*
38+
* Reference to the AnchorTagBuilder instance to use to generate an anchor
39+
* tag for the Match.
40+
*/
41+
42+
/**
43+
* @cfg {String} matchedText (required)
44+
*
45+
* The original text that was matched by the {@link Autolinker.matcher.Matcher}.
3846
*/
3947

4048
/**
41-
* @protected
42-
* @property {Number} offset
49+
* @cfg {Number} offset (required)
50+
*
51+
* The offset of where the match was made in the input string.
4352
*/
4453

4554

4655
/**
4756
* @constructor
48-
* @param {String} matchedText The original text that was matched.
49-
* @param {Number} offset The offset of where the match was made in the
50-
* input string.
57+
* @param {Object} cfg The configuration properties for the Match
58+
* instance, specified in an Object (map).
5159
*/
52-
constructor : function( matchedText, offset ) {
60+
constructor : function( cfg ) {
5361
// @if DEBUG
54-
if( matchedText == null ) throw new Error( '`matchedText` arg required' );
55-
if( offset == null ) throw new Error( '`offset` arg required' );
62+
if( cfg.tagBuilder == null ) throw new Error( '`tagBuilder` cfg required' );
63+
if( cfg.matchedText == null ) throw new Error( '`matchedText` cfg required' );
64+
if( cfg.offset == null ) throw new Error( '`offset` cfg required' );
5665
// @endif
5766

58-
this.matchedText = matchedText;
59-
this.offset = offset;
67+
this.tagBuilder = cfg.tagBuilder;
68+
this.matchedText = cfg.matchedText;
69+
this.offset = cfg.offset;
6070
},
6171

6272

@@ -122,6 +132,26 @@ Autolinker.match.Match = Autolinker.Util.extend( Object, {
122132
* @abstract
123133
* @return {String}
124134
*/
125-
getAnchorText : Autolinker.Util.abstractMethod
135+
getAnchorText : Autolinker.Util.abstractMethod,
136+
137+
138+
/**
139+
* Builds and returns an {@link Autolinker.HtmlTag} instance based on the
140+
* Match.
141+
*
142+
* This can be used to easily generate anchor tags from matches, and either
143+
* return their HTML string, or modify them before doing so.
144+
*
145+
* Example Usage:
146+
*
147+
* var tag = match.buildTag();
148+
* tag.addClass( 'cordova-link' );
149+
* tag.setAttr( 'target', '_system' );
150+
*
151+
* tag.toAnchorString(); // <a href="http://google.com" class="cordova-link" target="_system">Google</a>
152+
*/
153+
buildTag : function() {
154+
return this.tagBuilder.build( this );
155+
}
126156

127157
} );

src/match/Phone.js

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,19 @@ Autolinker.match.Phone = Autolinker.Util.extend( Autolinker.match.Match, {
3333

3434
/**
3535
* @constructor
36-
* @param {String} matchedText The original text that was matched.
37-
* @param {Number} offset The offset of where the match was made in the
38-
* input string.
39-
* @param {String} number The phone number that was matched, without any
40-
* delimiter characters. See {@link #number} for more details.
41-
* @param {Boolean} plusSign `true` if the matched phone number started with
42-
* a '+' sign. See {@link #plusSign} for more details.
36+
* @param {Object} cfg The configuration properties for the Match
37+
* instance, specified in an Object (map).
4338
*/
44-
constructor : function( matchedText, offset, number, plusSign ) {
45-
Autolinker.match.Match.prototype.constructor.call( this, matchedText, offset );
39+
constructor : function( cfg ) {
40+
Autolinker.match.Match.prototype.constructor.call( this, cfg );
4641

4742
// @if DEBUG
48-
if( !number ) throw new Error( '`number` arg required' );
49-
if( plusSign == null ) throw new Error( '`plusSign` arg required' );
43+
if( !cfg.number ) throw new Error( '`number` cfg required' );
44+
if( cfg.plusSign == null ) throw new Error( '`plusSign` cfg required' );
5045
// @endif
5146

52-
this.number = number;
53-
this.plusSign = plusSign;
47+
this.number = cfg.number;
48+
this.plusSign = cfg.plusSign;
5449
},
5550

5651

src/match/Twitter.js

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,25 @@
1010
Autolinker.match.Twitter = Autolinker.Util.extend( Autolinker.match.Match, {
1111

1212
/**
13-
* @protected
14-
* @property {String} twitterHandle (required)
13+
* @cfg {String} twitterHandle (required)
1514
*
1615
* The Twitter handle that was matched, without the '@' character.
1716
*/
1817

1918

2019
/**
2120
* @constructor
22-
* @param {String} matchedText The original text that was matched.
23-
* @param {Number} offset The offset of where the match was made in the
24-
* input string.
25-
* @param {String} twitterHandle The Twitter handle that was matched,
26-
* without the '@' character.
21+
* @param {Object} cfg The configuration properties for the Match
22+
* instance, specified in an Object (map).
2723
*/
28-
constructor : function( matchedText, offset, twitterHandle ) {
29-
Autolinker.match.Match.prototype.constructor.call( this, matchedText, offset );
24+
constructor : function( cfg) {
25+
Autolinker.match.Match.prototype.constructor.call( this, cfg );
3026

3127
// @if DEBUG
32-
if( !twitterHandle ) throw new Error( '`twitterHandle` arg required' );
28+
if( !cfg.twitterHandle ) throw new Error( '`twitterHandle` cfg required' );
3329
// @endif
3430

35-
this.twitterHandle = twitterHandle;
31+
this.twitterHandle = cfg.twitterHandle;
3632
},
3733

3834

0 commit comments

Comments
 (0)