+ Snippet:
+
+
+ Filter |
+ Source |
+ Rendered |
+
+
+ linky filter |
+
+ <div ng-bind-html="snippet | linky"> </div>
+ |
+
+
+ |
+
+
+ no filter |
+ <div ng-bind="snippet"> </div> |
+ |
+
+
+
+
+ it('should linkify the snippet with urls', function() {
+ expect(using('#linky-filter').binding('snippet | linky')).
+ toBe('Pretty text with some links:
' +
+ 'http://angularjs.org/,
' +
+ 'us@somewhere.org,
' +
+ 'another@somewhere.org,
' +
+ 'and one more: ftp://127.0.0.1/.');
+ });
+
+ it ('should not linkify snippet without the linky filter', function() {
+ expect(using('#escaped-html').binding('snippet')).
+ toBe("Pretty text with some links:\n" +
+ "http://angularjs.org/,\n" +
+ "mailto:us@somewhere.org,\n" +
+ "another@somewhere.org,\n" +
+ "and one more: ftp://127.0.0.1/.");
+ });
+
+ it('should update', function() {
+ input('snippet').enter('new http://link.');
+ expect(using('#linky-filter').binding('snippet | linky')).
+ toBe('new http://link.');
+ expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
+ });
+
+
+ */
+angular.module('ngSanitize').filter('linky', function() {
+ var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
+ MAILTO_REGEXP = /^mailto:/;
+
+ return function(text) {
+ if (!text) return text;
+ var match;
+ var raw = text;
+ var html = [];
+ // TODO(vojta): use $sanitize instead
+ var writer = htmlSanitizeWriter(html);
+ var url;
+ var i;
+ while ((match = raw.match(LINKY_URL_REGEXP))) {
+ // We can not end in these as they are sometimes found at the end of the sentence
+ url = match[0];
+ // if we did not match ftp/http/mailto then assume mailto
+ if (match[2] == match[3]) url = 'mailto:' + url;
+ i = match.index;
+ writer.chars(raw.substr(0, i));
+ writer.start('a', {href:url});
+ writer.chars(match[0].replace(MAILTO_REGEXP, ''));
+ writer.end('a');
+ raw = raw.substring(i + match[0].length);
+ }
+ writer.chars(raw);
+ return html.join('');
+ };
+});
+
+})(window, window.angular);
diff --git a/src/tooltip/docs/demo.js b/src/tooltip/docs/demo.js
index e31c64df07..6abdf6b1b0 100644
--- a/src/tooltip/docs/demo.js
+++ b/src/tooltip/docs/demo.js
@@ -1,4 +1,4 @@
var TooltipDemoCtrl = function ($scope) {
- $scope.dynamicTooltip = "Hello, World!";
+ $scope.dynamicTooltip = "Hello,
World!";
$scope.dynamicTooltipText = "dynamic";
};
diff --git a/src/tooltip/docs/readme.md b/src/tooltip/docs/readme.md
index abc53df636..5e461c8dbe 100644
--- a/src/tooltip/docs/readme.md
+++ b/src/tooltip/docs/readme.md
@@ -1,2 +1,5 @@
A lightweight, extensible directive for fancy tooltip creation. The tooltip
directive supports multiple placements, optional transition animation, and more.
+
+Tooltip content is automatically sanitized of dangerous HTML content using the
+ngSanitize module, which must be included.
diff --git a/src/tooltip/test/tooltip.spec.js b/src/tooltip/test/tooltip.spec.js
index 1eb537a7e8..205f5c0ea9 100644
--- a/src/tooltip/test/tooltip.spec.js
+++ b/src/tooltip/test/tooltip.spec.js
@@ -121,6 +121,34 @@ describe('tooltip', function() {
expect(elmBody.children().length).toBe(1);
}));
+
+ it( 'should allow HTML in the tooltip text', inject( function ( $compile ) {
+ scope.content = "Contains a
bold element";
+
+ elmBody = $compile( angular.element(
+ '
Selector text
'
+ ))( scope );
+ scope.$digest();
+
+ elmBody.find('span').trigger('mouseenter');
+ ttScope = angular.element( elmBody.children()[0] ).scope();
+
+ expect(ttScope.tt_tooltip).toBe(scope.content);
+ }));
+
+ it( 'should sanitize HTML in the tooltip text', inject( function ( $compile ) {
+ scope.content = "Contains an
unallowed element.";
+
+ elmBody = $compile( angular.element(
+ '
Selector text
'
+ ))( scope );
+ scope.$digest();
+
+ elmBody.find('span').trigger('mouseenter');
+ ttScope = angular.element( elmBody.children()[0] ).scope();
+
+ expect(ttScope.tt_tooltip).toBe("Contains an
unallowed element.");
+ }));
});
diff --git a/src/tooltip/tooltip.js b/src/tooltip/tooltip.js
index 7af22a45b3..cb0fe48031 100644
--- a/src/tooltip/tooltip.js
+++ b/src/tooltip/tooltip.js
@@ -3,7 +3,7 @@
* function, placement as a function, inside, support for more triggers than
* just mouse enter/leave, html tooltips, and selector delegatation.
*/
-angular.module( 'ui.bootstrap.tooltip', [] )
+angular.module( 'ui.bootstrap.tooltip', [ 'ngSanitize' ] )
.directive( 'tooltipPopup', function () {
return {
restrict: 'EA',
@@ -12,7 +12,7 @@ angular.module( 'ui.bootstrap.tooltip', [] )
templateUrl: 'template/tooltip/tooltip-popup.html'
};
})
-.directive( 'tooltip', [ '$compile', '$timeout', '$parse', '$window', function ( $compile, $timeout, $parse, $window) {
+.directive( 'tooltip', [ '$compile', '$timeout', '$parse', '$window', '$sanitize', function ( $compile, $timeout, $parse, $window, $sanitize) {
var template =
'
-
+
From 3175d40a8959acb1dd383834599ac99e73e51714 Mon Sep 17 00:00:00 2001
From: Josh David Miller