Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 9b4237e

Browse files
committed
feat(ngSanitize): Add custom attributes to linky
Optional extra attributes may be defined either as: - a map of attributes and values - a function that takes the url as a parameter and returns a map
1 parent d33cedd commit 9b4237e

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

src/ngSanitize/filter/linky.js

+45-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@
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
@@ -32,7 +42,7 @@
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">
@@ -55,10 +65,19 @@
5565
<tr id="linky-target">
5666
<td>linky target</td>
5767
<td>
58-
<pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
68+
<pre>&lt;div ng-bind-html="snippetWithSingleURL | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
5969
</td>
6070
<td>
61-
<div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
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>&lt;div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel:'nofollow'}"&gt;<br>&lt;/div&gt;</pre>
78+
</td>
79+
<td>
80+
<div ng-bind-html="snippetWithSingleURL | linky:'_self':{rel:'nofollow'}"></div>
6281
</td>
6382
</tr>
6483
<tr id="escaped-html">
@@ -95,10 +114,17 @@
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
/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
108134
MAILTO_REGEXP = /^mailto:/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,21 @@ angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
137163
}
138164

139165
function addLink(url, text) {
166+
var key;
167+
var computedAttributes = {};
140168
html.push('<a ');
141-
if (angular.isDefined(target)) {
169+
if (angular.isObject(attributes)) {
170+
computedAttributes = attributes;
171+
for (key in computedAttributes) {
172+
html.push(key + '="' + computedAttributes[key] + '" ');
173+
}
174+
} else if (angular.isFunction(attributes)) {
175+
computedAttributes = attributes(url);
176+
for (key in computedAttributes) {
177+
html.push(key + '="' + computedAttributes[key] + '" ');
178+
}
179+
}
180+
if (angular.isDefined(target) && !('target' in computedAttributes)) {
142181
html.push('target="',
143182
target,
144183
'" ');

test/ngSanitize/filter/linkySpec.js

+21
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,25 @@ describe('linky', function() {
5454
expect(linky("http://example.com", "someNamedIFrame")).
5555
toEqual('<a target="someNamedIFrame" href="http://example.com">http://example.com</a>');
5656
});
57+
58+
it('should optionally add custom attributes', function() {
59+
expect(linky("http://example.com", "_self", {rel: "nofollow"})).
60+
toEqual('<a rel="nofollow" target="_self" href="http://example.com">http://example.com</a>');
61+
});
62+
63+
it('should override target parameter with custom attributes', function() {
64+
expect(linky("http://example.com", "_self", {target: "_blank"})).
65+
toEqual('<a target="_blank" href="http://example.com">http://example.com</a>');
66+
});
67+
68+
it('should optionally add custom attributes from function', function() {
69+
expect(linky("http://example.com", "_self", function(url) {return {"class": "blue"};})).
70+
toEqual('<a class="blue" target="_self" href="http://example.com">http://example.com</a>');
71+
});
72+
73+
it('should pass url as parameter to custom attribute function', function() {
74+
var linkParameters = jasmine.createSpy('linkParameters').andReturn({"class": "blue"});
75+
linky("http://example.com", "_self", linkParameters);
76+
expect(linkParameters).toHaveBeenCalledWith('http://example.com');
77+
});
5778
});

0 commit comments

Comments
 (0)