1515 *
1616 * @param {string } text Input text.
1717 * @param {string } target Window (_blank|_self|_parent|_top) or named frame to open links in.
18+ * @param {object|function(url) } [attributes] Add custom attributes to the link element.
19+ *
20+ * Can be one of:
21+ *
22+ * - `object`: A map of attributes
23+ * - `function`: Takes the url as a parameter and returns a map of attributes
24+ *
25+ * If the map of attributes contains a value for `target`, it overrides the value of
26+ * the target parameter.
27+ *
1828 * @returns {string } Html-linkified text.
1929 *
2030 * @usage
3242 'mailto:us@somewhere .org,\n'+
3343 'another@somewhere.org,\n'+
3444 'and one more: ftp://127.0.0.1/.';
35- $scope.snippetWithTarget = 'http://angularjs.org/';
45+ $scope.snippetWithSingleURL = 'http://angularjs.org/';
3646 }]);
3747 </script>
3848 <div ng-controller="ExampleController">
5565 <tr id="linky-target">
5666 <td>linky target</td>
5767 <td>
58- <pre><div ng-bind-html="snippetWithTarget | linky:'_blank'"><br></div></pre>
68+ <pre><div ng-bind-html="snippetWithSingleURL | linky:'_blank'"><br></div></pre>
69+ </td>
70+ <td>
71+ <div ng-bind-html="snippetWithSingleURL | linky:'_blank'"></div>
72+ </td>
73+ </tr>
74+ <tr id="linky-custom-attributes">
75+ <td>linky custom attributes</td>
76+ <td>
77+ <pre><div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}"><br></div></pre>
5978 </td>
6079 <td>
61- <div ng-bind-html="snippetWithTarget | linky:'_blank' "></div>
80+ <div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel: 'nofollow'} "></div>
6281 </td>
6382 </tr>
6483 <tr id="escaped-html">
95114
96115 it('should work with the target property', function() {
97116 expect(element(by.id('linky-target')).
98- element(by.binding("snippetWithTarget | linky:'_blank'")).getText()).
117+ element(by.binding("snippetWithSingleURL | linky:'_blank'")).getText()).
99118 toBe('http://angularjs.org/');
100119 expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');
101120 });
121+
122+ it('should optionally add custom attributes', function() {
123+ expect(element(by.id('linky-custom-attributes')).
124+ element(by.binding("snippetWithSingleURL | linky:'_self':{rel: 'nofollow'}")).getText()).
125+ toBe('http://angularjs.org/');
126+ expect(element(by.css('#linky-custom-attributes a')).getAttribute('rel')).toEqual('nofollow');
127+ });
102128 </file>
103129 </example>
104130 */
@@ -107,7 +133,7 @@ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
107133 / ( ( f t p | h t t p s ? ) : \/ \/ | ( w w w \. ) | ( m a i l t o : ) ? [ A - Z a - z 0 - 9 . _ % + - ] + @ ) \S * [ ^ \s . ; , ( ) { } < > " \u201d \u2019 ] / i,
108134 MAILTO_REGEXP = / ^ m a i l t o : / i;
109135
110- return function ( text , target ) {
136+ return function ( text , target , attributes ) {
111137 if ( ! text ) return text ;
112138 var match ;
113139 var raw = text ;
@@ -137,8 +163,19 @@ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
137163 }
138164
139165 function addLink ( url , text ) {
166+ var key ;
140167 html . push ( '<a ' ) ;
141- if ( angular . isDefined ( target ) ) {
168+ if ( angular . isFunction ( attributes ) ) {
169+ attributes = attributes ( url ) ;
170+ }
171+ if ( angular . isObject ( attributes ) ) {
172+ for ( key in attributes ) {
173+ html . push ( key + '="' + attributes [ key ] + '" ' ) ;
174+ }
175+ } else {
176+ attributes = { } ;
177+ }
178+ if ( angular . isDefined ( target ) && ! ( 'target' in attributes ) ) {
142179 html . push ( 'target="' ,
143180 target ,
144181 '" ' ) ;
0 commit comments