From 28ed0ba8bdcdda6f7767a5d0efa24c80a0655314 Mon Sep 17 00:00:00 2001 From: Wesley Cho Date: Sun, 2 Aug 2015 02:14:07 -0700 Subject: [PATCH] feat(typeahead): *BREAKING CHANGE* switch to `ngBindHtml` - Remove usage of `bindHtmlUnsafe` in typeahead - Integrate usage of `$sce` in combination with `ngBindHtml` --- src/typeahead/docs/demo.html | 2 +- src/typeahead/docs/readme.md | 4 +++ .../test/typeahead-highlight.spec.js | 26 ++++++++++--------- src/typeahead/typeahead.js | 4 +-- template/typeahead/typeahead-match.html | 2 +- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/typeahead/docs/demo.html b/src/typeahead/docs/demo.html index 3808bc854d..4492e8ab48 100644 --- a/src/typeahead/docs/demo.html +++ b/src/typeahead/docs/demo.html @@ -1,7 +1,7 @@
diff --git a/src/typeahead/docs/readme.md b/src/typeahead/docs/readme.md index 8415064b1b..44c0f1a350 100644 --- a/src/typeahead/docs/readme.md +++ b/src/typeahead/docs/readme.md @@ -67,3 +67,7 @@ The typeahead directives provide several attributes: * `typeahead-select-on-blur` _(Defaults: false)_ : On blur, select the currently highlighted match + +**BREAKING CHANGE** + +This component now automatically whitelists HTML with the `typeaheadHighlight` filter & users `ngBindHtml` instead of the custom `bindHtmlUnsafe` directive in the match template. If more granular security is desired, it is recommended to use a custom match template with a custom filter to enforce security more strictly. diff --git a/src/typeahead/test/typeahead-highlight.spec.js b/src/typeahead/test/typeahead-highlight.spec.js index 1a5aafc48d..0120210798 100644 --- a/src/typeahead/test/typeahead-highlight.spec.js +++ b/src/typeahead/test/typeahead-highlight.spec.js @@ -1,39 +1,41 @@ describe('typeaheadHighlight', function () { - var highlightFilter; + var highlightFilterValue; beforeEach(module('ui.bootstrap.typeahead')); - beforeEach(inject(function (typeaheadHighlightFilter) { - highlightFilter = typeaheadHighlightFilter; + beforeEach(inject(function ($sce, typeaheadHighlightFilter) { + highlightFilterValue = function() { + return $sce.getTrustedHtml(typeaheadHighlightFilter.apply(null, Array.prototype.slice.call(arguments))); + }; })); it('should higlight a match', function () { - expect(highlightFilter('before match after', 'match')).toEqual('before match after'); + expect(highlightFilterValue('before match after', 'match')).toEqual('before match after'); }); it('should higlight a match with mixed case', function () { - expect(highlightFilter('before MaTch after', 'match')).toEqual('before MaTch after'); + expect(highlightFilterValue('before MaTch after', 'match')).toEqual('before MaTch after'); }); it('should higlight all matches', function () { - expect(highlightFilter('before MaTch after match', 'match')).toEqual('before MaTch after match'); + expect(highlightFilterValue('before MaTch after match', 'match')).toEqual('before MaTch after match'); }); it('should do nothing if no match', function () { - expect(highlightFilter('before match after', 'nomatch')).toEqual('before match after'); + expect(highlightFilterValue('before match after', 'nomatch')).toEqual('before match after'); }); it('should do nothing if no or empty query', function () { - expect(highlightFilter('before match after', '')).toEqual('before match after'); - expect(highlightFilter('before match after', null)).toEqual('before match after'); - expect(highlightFilter('before match after', undefined)).toEqual('before match after'); + expect(highlightFilterValue('before match after', '')).toEqual('before match after'); + expect(highlightFilterValue('before match after', null)).toEqual('before match after'); + expect(highlightFilterValue('before match after', undefined)).toEqual('before match after'); }); it('issue 316 - should work correctly for regexp reserved words', function () { - expect(highlightFilter('before (match after', '(match')).toEqual('before (match after'); + expect(highlightFilterValue('before (match after', '(match')).toEqual('before (match after'); }); it('issue 1777 - should work correctly with numeric values', function () { - expect(highlightFilter(123, '2')).toEqual('123'); + expect(highlightFilterValue(123, '2')).toEqual('123'); }); }); diff --git a/src/typeahead/typeahead.js b/src/typeahead/typeahead.js index bc6c57146d..36d422dedf 100644 --- a/src/typeahead/typeahead.js +++ b/src/typeahead/typeahead.js @@ -492,13 +492,13 @@ angular.module('ui.bootstrap.typeahead', ['ui.bootstrap.position', 'ui.bootstrap }; }]) - .filter('typeaheadHighlight', function() { + .filter('typeaheadHighlight', function($sce) { function escapeRegexp(queryToEscape) { return queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1'); } return function(matchItem, query) { - return query ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&') : matchItem; + return query ? $sce.trustAsHtml(('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '$&')) : $sce.trustAsHtml(matchItem); }; }); diff --git a/template/typeahead/typeahead-match.html b/template/typeahead/typeahead-match.html index 368fd0bf59..2e7ff9e023 100644 --- a/template/typeahead/typeahead-match.html +++ b/template/typeahead/typeahead-match.html @@ -1 +1 @@ - +