chore(ngSanitize): extract $sanitize, ngBindHtml, linkyFilter into a module

Create build for other modules as well (ngResource, ngCookies):
- wrap into a function
- add license
- add version

Breaks `$sanitize` service, `ngBindHtml` directive and `linky` filter were moved to the `ngSanitize` module. Apps that depend on any of these will need to load `angular-sanitize.js` and include `ngSanitize` in their dependency list: `var myApp = angular.module('myApp', ['ngSanitize']);`
This commit is contained in:
Vojta Jina
2012-04-10 16:50:31 -07:00
parent e1743cc837
commit 5bcd719866
20 changed files with 301 additions and 244 deletions

View File

@@ -82,15 +82,23 @@ task :compile => [:init, :compile_scenario, :compile_jstd_scenario_adapter] do
'src/loader.js',
'src/loader.suffix'])
FileUtils.cp 'src/ngMock/angular-mocks.js', path_to('angular-mocks.js')
FileUtils.cp 'src/ngResource/resource.js', path_to('angular-resource.js')
FileUtils.cp 'src/ngCookies/cookies.js', path_to('angular-cookies.js')
concat_module('sanitize', [
'src/ngSanitize/sanitize.js',
'src/ngSanitize/directive/ngBindHtml.js',
'src/ngSanitize/filter/linky.js'])
concat_module('resource', ['src/ngResource/resource.js'])
concat_module('cookies', ['src/ngCookies/cookies.js'])
FileUtils.cp 'src/ngMock/angular-mocks.js', path_to('angular-mocks.js')
closure_compile('angular.js')
closure_compile('angular-cookies.js')
closure_compile('angular-loader.js')
closure_compile('angular-resource.js')
closure_compile('angular-sanitize.js')
end
@@ -121,6 +129,8 @@ task :package => [:clean, :compile, :docs] do
path_to('angular-cookies.min.js'),
path_to('angular-resource.js'),
path_to('angular-resource.min.js'),
path_to('angular-sanitize.js'),
path_to('angular-sanitize.min.js'),
path_to('angular-scenario.js'),
path_to('jstd-scenario-adapter.js'),
path_to('jstd-scenario-adapter-config.js'),
@@ -147,7 +157,8 @@ task :package => [:clean, :compile, :docs] do
rewrite_file(src) do |content|
content.sub!('angular.js', "angular-#{NG_VERSION.full}.js").
sub!('angular-resource.js', "angular-resource-#{NG_VERSION.full}.js").
sub!('angular-cookies.js', "angular-cookies-#{NG_VERSION.full}.js")
sub!('angular-cookies.js', "angular-cookies-#{NG_VERSION.full}.js").
sub!('angular-sanitize.js', "angular-sanitize-#{NG_VERSION.full}.js")
end
end
@@ -290,6 +301,11 @@ def concat_file(filename, deps, footer='')
end
def concat_module(name, files)
concat_file('angular-' + name + '.js', ['src/module.prefix'] + files + ['src/module.suffix'])
end
def rewrite_file(filename)
File.open(filename, File::RDWR) do |f|
content = f.read

15
angularFiles.js vendored
View File

@@ -24,7 +24,6 @@ angularFiles = {
'src/ng/route.js',
'src/ng/routeParams.js',
'src/ng/rootScope.js',
'src/ng/sanitize.js',
'src/ng/sniffer.js',
'src/ng/window.js',
'src/ng/http.js',
@@ -65,6 +64,9 @@ angularFiles = {
'angularSrcModules': [
'src/ngCookies/cookies.js',
'src/ngResource/resource.js',
'src/ngSanitize/sanitize.js',
'src/ngSanitize/directive/ngBindHtml.js',
'src/ngSanitize/filter/linky.js',
'src/ngMock/angular-mocks.js'
],
@@ -98,6 +100,9 @@ angularFiles = {
'test/ng/filter/*.js',
'test/ngCookies/*.js',
'test/ngResource/*.js',
'test/ngSanitize/*.js',
'test/ngSanitize/directive/*.js',
'test/ngSanitize/filter/*.js',
'test/ngMock/*.js'
],
@@ -136,10 +141,16 @@ angularFiles = {
'src/ngMock/angular-mocks.js',
'src/ngCookies/cookies.js',
'src/ngResource/resource.js',
'src/ngSanitize/sanitize.js',
'src/ngSanitize/directive/ngBindHtml.js',
'src/ngSanitize/filter/linky.js',
'test/matchers.js',
'test/ngMock/*.js',
'test/ngCookies/*.js',
'test/ngResource/*.js'
'test/ngResource/*.js',
'test/ngSanitize/*.js',
'test/ngSanitize/directive/*.js',
'test/ngSanitize/filter/*.js'
],
'jstdPerf': [

View File

@@ -39,7 +39,7 @@ The two partials are defined in the following URLs:
<doc:example module="deepLinking">
<doc:source jsfiddle="false">
<script>
angular.module('deepLinking', [])
angular.module('deepLinking', ['ngSanitize'])
.config(function($routeProvider) {
$routeProvider.when("/welcome", {template:'./examples/welcome.html', controller:WelcomeCntl});
$routeProvider.when("/settings", {template:'./examples/settings.html', controller:SettingsCntl});

View File

@@ -146,7 +146,8 @@ function TutorialInstructionsCtrl($scope, $cookieStore) {
};
}
angular.module('ngdocs', ['ngdocs.directives', 'ngResource', 'ngCookies'], function($locationProvider, $filterProvider, $compileProvider) {
angular.module('ngdocs', ['ngdocs.directives', 'ngResource', 'ngCookies', 'ngSanitize'],
function($locationProvider, $filterProvider, $compileProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
$filterProvider.register('title', function(){

View File

@@ -30,6 +30,7 @@
addTag('script', {src: path('angular.js')}, sync);
addTag('script', {src: path('angular-resource.js') }, sync);
addTag('script', {src: path('angular-cookies.js') }, sync);
addTag('script', {src: path('angular-sanitize.js') }, sync);
addTag('script', {src: 'docs-combined.js'}, sync);
addTag('script', {src: 'docs-keywords.js'}, sync);

View File

@@ -71,7 +71,6 @@ function publishExternalAPI(angular){
style: styleDirective,
option: optionDirective,
ngBind: ngBindDirective,
ngBindHtml: ngBindHtmlDirective,
ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective,
ngBindTemplate: ngBindTemplateDirective,
ngClass: ngClassDirective,
@@ -123,7 +122,6 @@ function publishExternalAPI(angular){
$routeParams: $RouteParamsProvider,
$rootScope: $RootScopeProvider,
$q: $QProvider,
$sanitize: $SanitizeProvider,
$sniffer: $SnifferProvider,
$templateCache: $TemplateCacheProvider,
$window: $WindowProvider

6
src/module.prefix Normal file
View File

@@ -0,0 +1,6 @@
/**
* @license AngularJS v"NG_VERSION_FULL"
* (c) 2010-2012 AngularJS http://angularjs.org
* License: MIT
*/
(function(angular) {

2
src/module.suffix Normal file
View File

@@ -0,0 +1,2 @@
})(window.angular);

View File

@@ -55,54 +55,6 @@ var ngBindDirective = ngDirective(function(scope, element, attr) {
});
/**
* @ngdoc directive
* @name angular.module.ng.$compileProvider.directive.ngBindHtmlUnsafe
*
* @description
* Creates a binding that will innerHTML the result of evaluating the `expression` into the current
* element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if
* {@link angular.module.ng.$compileProvider.directive.ngBindHtml ngBindHtml} directive is too
* restrictive and when you absolutely trust the source of the content you are binding to.
*
* See {@link angular.module.ng.$sanitize $sanitize} docs for examples.
*
* @element ANY
* @param {expression} ngBindHtmlUnsafe {@link guide/dev_guide.expressions Expression} to evaluate.
*/
var ngBindHtmlUnsafeDirective = ngDirective(function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);
scope.$watch(attr.ngBindHtmlUnsafe, function(value) {
element.html(value || '');
});
});
/**
* @ngdoc directive
* @name angular.module.ng.$compileProvider.directive.ngBindHtml
*
* @description
* Creates a binding that will sanitize the result of evaluating the `expression` with the
* {@link angular.module.ng.$sanitize $sanitize} service and innerHTML the result into the current
* element.
*
* See {@link angular.module.ng.$sanitize $sanitize} docs for examples.
*
* @element ANY
* @param {expression} ngBindHtml {@link guide/dev_guide.expressions Expression} to evaluate.
*/
var ngBindHtmlDirective = ['$sanitize', function($sanitize) {
return function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBindHtml);
scope.$watch(attr.ngBindHtml, function(value) {
value = $sanitize(value);
element.html(value || '');
});
}
}];
/**
* @ngdoc directive
* @name angular.module.ng.$compileProvider.directive.ngBindTemplate
@@ -160,3 +112,28 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
});
}
}];
/**
* @ngdoc directive
* @name angular.module.ng.$compileProvider.directive.ngBindHtmlUnsafe
*
* @description
* Creates a binding that will innerHTML the result of evaluating the `expression` into the current
* element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if
* {@link angular.module.ng.$compileProvider.directive.ngBindHtml ngBindHtml} directive is too
* restrictive and when you absolutely trust the source of the content you are binding to.
*
* See {@link angular.module.ng.$sanitize $sanitize} docs for examples.
*
* @element ANY
* @param {expression} ngBindHtmlUnsafe {@link guide/dev_guide.expressions Expression} to evaluate.
*/
var ngBindHtmlUnsafeDirective = [function() {
return function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe);
scope.$watch(attr.ngBindHtmlUnsafe, function(value) {
element.html(value || '');
});
};
}];

View File

@@ -96,7 +96,6 @@ function $FilterProvider($provide) {
register('filter', filterFilter);
register('json', jsonFilter);
register('limitTo', limitToFilter);
register('linky', linkyFilter);
register('lowercase', lowercaseFilter);
register('number', numberFilter);
register('orderBy', orderByFilter);

View File

@@ -439,110 +439,3 @@ var lowercaseFilter = valueFn(lowercase);
* @see angular.uppercase
*/
var uppercaseFilter = valueFn(uppercase);
/**
* @ngdoc filter
* @name angular.module.ng.$filter.linky
* @function
*
* @description
* Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
* plain email address links.
*
* @param {string} text Input text.
* @returns {string} Html-linkified text.
*
* @example
<doc:example>
<doc:source>
<script>
function Ctrl($scope) {
$scope.snippet =
'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/.';
}
</script>
<div ng-controller="Ctrl">
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
<table>
<tr>
<td>Filter</td>
<td>Source</td>
<td>Rendered</td>
</tr>
<tr id="linky-filter">
<td>linky filter</td>
<td>
<pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
</td>
<td>
<div ng-bind-html="snippet | linky"></div>
</td>
</tr>
<tr id="escaped-html">
<td>no filter</td>
<td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
<td><div ng-bind="snippet"></div></td>
</tr>
</table>
</doc:source>
<doc:scenario>
it('should linkify the snippet with urls', function() {
expect(using('#linky-filter').binding('snippet | linky')).
toBe('Pretty text with some links:&#10;' +
'<a href="http://angularjs.org/">http://angularjs.org/</a>,&#10;' +
'<a href="mailto:us@somewhere.org">us@somewhere.org</a>,&#10;' +
'<a href="mailto:another@somewhere.org">another@somewhere.org</a>,&#10;' +
'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
});
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 <a href="http://link">http://link</a>.');
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
});
</doc:scenario>
</doc:example>
*/
function linkyFilter() {
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 = [];
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('');
};
}

View File

@@ -0,0 +1,26 @@
/**
* @ngdoc directive
* @name angular.module.ngSanitize.directive.ngBindHtml
*
* @description
* Creates a binding that will sanitize the result of evaluating the `expression` with the
* {@link angular.module.ng.$sanitize $sanitize} service and innerHTML the result into the current
* element.
*
* See {@link angular.module.ng.$sanitize $sanitize} docs for examples.
*
* @element ANY
* @param {expression} ngBindHtml {@link guide/dev_guide.expressions Expression} to evaluate.
*/
angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) {
return function(scope, element, attr) {
element.addClass('ng-binding').data('$binding', attr.ngBindHtml);
scope.$watch(attr.ngBindHtml, function(value) {
value = $sanitize(value);
element.html(value || '');
});
};
}]);

View File

@@ -0,0 +1,106 @@
/**
* @ngdoc filter
* @name angular.module.ngSanitize.filter.linky
* @function
*
* @description
* Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
* plain email address links.
*
* @param {string} text Input text.
* @returns {string} Html-linkified text.
*
* @example
<doc:example module="ngSanitize">
<doc:source>
<script>
function Ctrl($scope) {
$scope.snippet =
'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/.';
}
</script>
<div ng-controller="Ctrl">
Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
<table>
<tr>
<td>Filter</td>
<td>Source</td>
<td>Rendered</td>
</tr>
<tr id="linky-filter">
<td>linky filter</td>
<td>
<pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
</td>
<td>
<div ng-bind-html="snippet | linky"></div>
</td>
</tr>
<tr id="escaped-html">
<td>no filter</td>
<td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
<td><div ng-bind="snippet"></div></td>
</tr>
</table>
</doc:source>
<doc:scenario>
it('should linkify the snippet with urls', function() {
expect(using('#linky-filter').binding('snippet | linky')).
toBe('Pretty text with some links:&#10;' +
'<a href="http://angularjs.org/">http://angularjs.org/</a>,&#10;' +
'<a href="mailto:us@somewhere.org">us@somewhere.org</a>,&#10;' +
'<a href="mailto:another@somewhere.org">another@somewhere.org</a>,&#10;' +
'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
});
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 <a href="http://link">http://link</a>.');
expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
});
</doc:scenario>
</doc:example>
*/
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('');
};
});

View File

@@ -1,5 +1,11 @@
'use strict';
/**
* @ngdoc overview
* @name angular.module.ngSanitize
* @description
*/
/*
* HTML Parser By Misko Hevery (misko@hevery.com)
* based on: HTML Parser By John Resig (ejohn.org)
@@ -17,10 +23,9 @@
*/
/**
* @ngdoc service
* @name angular.module.ng.$sanitize
* @name angular.module.ngSanitize.$sanitize
* @function
*
* @description
@@ -34,7 +39,7 @@
* @returns {string} Sanitized html.
*
* @example
<doc:example>
<doc:example module="ngSanitize">
<doc:source>
<script>
function Ctrl($scope) {
@@ -103,14 +108,12 @@
</doc:scenario>
</doc:example>
*/
function $SanitizeProvider() {
this.$get = valueFn(function(html) {
var buf = [];
var $sanitize = function(html) {
var buf = [];
htmlParser(html, htmlSanitizeWriter(buf));
return buf.join('');
});
}
};
// Regular Expressions for parsing tags and attributes
var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
@@ -136,15 +139,15 @@ var voidElements = makeMap("area,br,col,hr,img,wbr");
// http://dev.w3.org/html5/spec/Overview.html#optional-tags
var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
optionalEndTagInlineElements = makeMap("rp,rt"),
optionalEndTagElements = extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);
optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements);
// Safe Block Elements - HTML5
var blockElements = extend({}, optionalEndTagBlockElements, makeMap("address,article,aside," +
var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article,aside," +
"blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6," +
"header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
// Inline Elements - HTML5
var inlineElements = extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b,bdi,bdo," +
var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b,bdi,bdo," +
"big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small," +
"span,strike,strong,sub,sup,time,tt,u,var"));
@@ -152,17 +155,24 @@ var inlineElements = extend({}, optionalEndTagInlineElements, makeMap("a,abbr,ac
// Special Elements (can contain anything)
var specialElements = makeMap("script,style");
var validElements = extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);
var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements);
//Attributes that have href and hence need to be sanitized
var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
var validAttrs = extend({}, uriAttrs, makeMap(
var validAttrs = angular.extend({}, uriAttrs, makeMap(
'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
'scope,scrolling,shape,span,start,summary,target,title,type,'+
'valign,value,vspace,width'));
function makeMap(str) {
var obj = {}, items = str.split(','), i;
for (i = 0; i < items.length; i++) obj[items[i]] = true;
return obj;
}
/**
* @example
* htmlParser(htmlString, {
@@ -249,7 +259,7 @@ function htmlParser( html, handler ) {
parseEndTag();
function parseStartTag( tag, tagName, rest, unary ) {
tagName = lowercase(tagName);
tagName = angular.lowercase(tagName);
if ( blockElements[ tagName ] ) {
while ( stack.last() && inlineElements[ stack.last() ] ) {
parseEndTag( "", stack.last() );
@@ -280,7 +290,7 @@ function htmlParser( html, handler ) {
function parseEndTag( tag, tagName ) {
var pos = 0, i;
tagName = lowercase(tagName);
tagName = angular.lowercase(tagName);
if ( tagName )
// Find the closest opened tag of the same type
for ( pos = stack.length - 1; pos >= 0; pos-- )
@@ -338,18 +348,18 @@ function encodeEntities(value) {
*/
function htmlSanitizeWriter(buf){
var ignore = false;
var out = bind(buf, buf.push);
var out = angular.bind(buf, buf.push);
return {
start: function(tag, attrs, unary){
tag = lowercase(tag);
tag = angular.lowercase(tag);
if (!ignore && specialElements[tag]) {
ignore = tag;
}
if (!ignore && validElements[tag] == true) {
out('<');
out(tag);
forEach(attrs, function(value, key){
var lkey=lowercase(key);
angular.forEach(attrs, function(value, key){
var lkey=angular.lowercase(key);
if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) {
out(' ');
out(key);
@@ -362,7 +372,7 @@ function htmlSanitizeWriter(buf){
}
},
end: function(tag){
tag = lowercase(tag);
tag = angular.lowercase(tag);
if (!ignore && validElements[tag] == true) {
out('</');
out(tag);
@@ -379,3 +389,7 @@ function htmlSanitizeWriter(buf){
}
};
}
// define ngSanitize module and register $sanitize service
angular.module('ngSanitize', []).value('$sanitize', $sanitize);

View File

@@ -67,39 +67,13 @@ describe('ngBind*', function() {
});
describe('ngBindHtml', function() {
it('should set html', inject(function($rootScope, $compile) {
element = $compile('<div ng-bind-html="html"></div>')($rootScope);
$rootScope.html = '<div unknown>hello</div>';
$rootScope.$digest();
expect(lowercase(element.html())).toEqual('<div>hello</div>');
}));
it('should reset html when value is null or undefined', inject(function($compile, $rootScope) {
element = $compile('<div ng-bind-html="html"></div>')($rootScope);
forEach([null, undefined, ''], function(val) {
$rootScope.html = 'some val';
$rootScope.$digest();
expect(lowercase(element.html())).toEqual('some val');
$rootScope.html = val;
$rootScope.$digest();
expect(lowercase(element.html())).toEqual('');
});
}));
});
describe('ngBindHtmlUnsafe', function() {
it('should set unsafe html', inject(function($rootScope, $compile) {
element = $compile('<div ng-bind-html-unsafe="html"></div>')($rootScope);
$rootScope.html = '<div onclick="">hello</div>';
$rootScope.$digest();
expect(lowercase(element.html())).toEqual('<div onclick="">hello</div>');
expect(angular.lowercase(element.html())).toEqual('<div onclick="">hello</div>');
}));
});
});

View File

@@ -153,32 +153,6 @@ describe('filters', function() {
});
});
describe('linky', function() {
var linky;
beforeEach(inject(function($filter){
linky = $filter('linky')
}));
it('should do basic filter', function() {
expect(linky("http://ab/ (http://a/) <http://a/> http://1.2/v:~-123. c")).
toEqual('<a href="http://ab/">http://ab/</a> ' +
'(<a href="http://a/">http://a/</a>) ' +
'&lt;<a href="http://a/">http://a/</a>&gt; ' +
'<a href="http://1.2/v:~-123">http://1.2/v:~-123</a>. c');
expect(linky(undefined)).not.toBeDefined();
});
it('should handle mailto:', function() {
expect(linky("mailto:me@example.com")).
toEqual('<a href="mailto:me@example.com">me@example.com</a>');
expect(linky("me@example.com")).
toEqual('<a href="mailto:me@example.com">me@example.com</a>');
expect(linky("send email to me@example.com, but")).
toEqual('send email to <a href="mailto:me@example.com">me@example.com</a>, but');
});
});
describe('date', function() {
var morning = new angular.mock.TzDate(+5, '2010-09-03T12:05:08.000Z'); //7am

View File

@@ -0,0 +1,25 @@
describe('ngBindHtml', function() {
beforeEach(module('ngSanitize'));
it('should set html', inject(function($rootScope, $compile) {
element = $compile('<div ng-bind-html="html"></div>')($rootScope);
$rootScope.html = '<div unknown>hello</div>';
$rootScope.$digest();
expect(angular.lowercase(element.html())).toEqual('<div>hello</div>');
}));
it('should reset html when value is null or undefined', inject(function($compile, $rootScope) {
element = $compile('<div ng-bind-html="html"></div>')($rootScope);
angular.forEach([null, undefined, ''], function(val) {
$rootScope.html = 'some val';
$rootScope.$digest();
expect(angular.lowercase(element.html())).toEqual('some val');
$rootScope.html = val;
$rootScope.$digest();
expect(angular.lowercase(element.html())).toEqual('');
});
}));
});

View File

@@ -0,0 +1,27 @@
describe('linky', function() {
var linky;
beforeEach(module('ngSanitize'));
beforeEach(inject(function($filter){
linky = $filter('linky');
}));
it('should do basic filter', function() {
expect(linky("http://ab/ (http://a/) <http://a/> http://1.2/v:~-123. c")).
toEqual('<a href="http://ab/">http://ab/</a> ' +
'(<a href="http://a/">http://a/</a>) ' +
'&lt;<a href="http://a/">http://a/</a>&gt; ' +
'<a href="http://1.2/v:~-123">http://1.2/v:~-123</a>. c');
expect(linky(undefined)).not.toBeDefined();
});
it('should handle mailto:', function() {
expect(linky("mailto:me@example.com")).
toEqual('<a href="mailto:me@example.com">me@example.com</a>');
expect(linky("me@example.com")).
toEqual('<a href="mailto:me@example.com">me@example.com</a>');
expect(linky("send email to me@example.com, but")).
toEqual('send email to <a href="mailto:me@example.com">me@example.com</a>, but');
});
});

View File

@@ -4,6 +4,8 @@ describe('HTML', function() {
var expectHTML;
beforeEach(module('ngSanitize'));
beforeEach(inject(function($sanitize) {
expectHTML = function(html){
return expect($sanitize(html));
@@ -11,6 +13,8 @@ describe('HTML', function() {
}));
describe('htmlParser', function() {
if (angular.isUndefined(window.htmlParser)) return;
var handler, start, text;
beforeEach(function() {
handler = {
@@ -22,8 +26,8 @@ describe('HTML', function() {
};
// Since different browsers handle newlines differenttly we trim
// so that it is easier to write tests.
forEach(attrs, function(value, key){
attrs[key] = trim(value);
angular.forEach(attrs, function(value, key) {
attrs[key] = value.replace(/^\s*/, '').replace(/\s*$/, '')
});
},
chars: function(text_){
@@ -64,9 +68,9 @@ describe('HTML', function() {
expect(start).toEqual({tag:'option', attrs:{selected:'', value:''}, unary:false});
expect(text).toEqual('abc');
});
});
// THESE TESTS ARE EXECUTED WITH COMPILED ANGULAR
it('should echo html', function() {
expectHTML('hello<b class="1\'23" align=\'""\'>world</b>.').
toEqual('hello<b class="1\'23" align="&#34;&#34;">world</b>.');
@@ -141,6 +145,8 @@ describe('HTML', function() {
});
describe('htmlSanitizerWriter', function() {
if (angular.isUndefined(window.htmlSanitizeWriter)) return;
var writer, html;
beforeEach(function() {
html = '';
@@ -277,5 +283,4 @@ describe('HTML', function() {
});
});
});

View File

@@ -9,6 +9,8 @@ describe("angular.scenario.dsl", function() {
dealoc(element);
});
beforeEach(module('ngSanitize'));
beforeEach(inject(function($injector) {
eventLog = [];
$window = {