angularjs-rails-resource 2.2.2 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,622 +0,0 @@
1
- /**
2
- * @license AngularJS v1.2.6
3
- * (c) 2010-2014 Google, Inc. http://angularjs.org
4
- * License: MIT
5
- */
6
- (function(window, angular, undefined) {'use strict';
7
-
8
- var $sanitizeMinErr = angular.$$minErr('$sanitize');
9
-
10
- /**
11
- * @ngdoc overview
12
- * @name ngSanitize
13
- * @description
14
- *
15
- * # ngSanitize
16
- *
17
- * The `ngSanitize` module provides functionality to sanitize HTML.
18
- *
19
- * {@installModule sanitize}
20
- *
21
- * <div doc-module-components="ngSanitize"></div>
22
- *
23
- * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
24
- */
25
-
26
- /*
27
- * HTML Parser By Misko Hevery (misko@hevery.com)
28
- * based on: HTML Parser By John Resig (ejohn.org)
29
- * Original code by Erik Arvidsson, Mozilla Public License
30
- * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
31
- *
32
- * // Use like so:
33
- * htmlParser(htmlString, {
34
- * start: function(tag, attrs, unary) {},
35
- * end: function(tag) {},
36
- * chars: function(text) {},
37
- * comment: function(text) {}
38
- * });
39
- *
40
- */
41
-
42
-
43
- /**
44
- * @ngdoc service
45
- * @name ngSanitize.$sanitize
46
- * @function
47
- *
48
- * @description
49
- * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are
50
- * then serialized back to properly escaped html string. This means that no unsafe input can make
51
- * it into the returned string, however, since our parser is more strict than a typical browser
52
- * parser, it's possible that some obscure input, which would be recognized as valid HTML by a
53
- * browser, won't make it through the sanitizer.
54
- * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
55
- * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
56
- *
57
- * @param {string} html Html input.
58
- * @returns {string} Sanitized html.
59
- *
60
- * @example
61
- <doc:example module="ngSanitize">
62
- <doc:source>
63
- <script>
64
- function Ctrl($scope, $sce) {
65
- $scope.snippet =
66
- '<p style="color:blue">an html\n' +
67
- '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
68
- 'snippet</p>';
69
- $scope.deliberatelyTrustDangerousSnippet = function() {
70
- return $sce.trustAsHtml($scope.snippet);
71
- };
72
- }
73
- </script>
74
- <div ng-controller="Ctrl">
75
- Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
76
- <table>
77
- <tr>
78
- <td>Directive</td>
79
- <td>How</td>
80
- <td>Source</td>
81
- <td>Rendered</td>
82
- </tr>
83
- <tr id="bind-html-with-sanitize">
84
- <td>ng-bind-html</td>
85
- <td>Automatically uses $sanitize</td>
86
- <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
87
- <td><div ng-bind-html="snippet"></div></td>
88
- </tr>
89
- <tr id="bind-html-with-trust">
90
- <td>ng-bind-html</td>
91
- <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
92
- <td>
93
- <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
94
- &lt;/div&gt;</pre>
95
- </td>
96
- <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
97
- </tr>
98
- <tr id="bind-default">
99
- <td>ng-bind</td>
100
- <td>Automatically escapes</td>
101
- <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
102
- <td><div ng-bind="snippet"></div></td>
103
- </tr>
104
- </table>
105
- </div>
106
- </doc:source>
107
- <doc:scenario>
108
- it('should sanitize the html snippet by default', function() {
109
- expect(using('#bind-html-with-sanitize').element('div').html()).
110
- toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
111
- });
112
-
113
- it('should inline raw snippet if bound to a trusted value', function() {
114
- expect(using('#bind-html-with-trust').element("div").html()).
115
- toBe("<p style=\"color:blue\">an html\n" +
116
- "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
117
- "snippet</p>");
118
- });
119
-
120
- it('should escape snippet without any filter', function() {
121
- expect(using('#bind-default').element('div').html()).
122
- toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
123
- "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
124
- "snippet&lt;/p&gt;");
125
- });
126
-
127
- it('should update', function() {
128
- input('snippet').enter('new <b onclick="alert(1)">text</b>');
129
- expect(using('#bind-html-with-sanitize').element('div').html()).toBe('new <b>text</b>');
130
- expect(using('#bind-html-with-trust').element('div').html()).toBe(
131
- 'new <b onclick="alert(1)">text</b>');
132
- expect(using('#bind-default').element('div').html()).toBe(
133
- "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
134
- });
135
- </doc:scenario>
136
- </doc:example>
137
- */
138
- function $SanitizeProvider() {
139
- this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
140
- return function(html) {
141
- var buf = [];
142
- htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
143
- return !/^unsafe/.test($$sanitizeUri(uri, isImage));
144
- }));
145
- return buf.join('');
146
- };
147
- }];
148
- }
149
-
150
- function sanitizeText(chars) {
151
- var buf = [];
152
- var writer = htmlSanitizeWriter(buf, angular.noop);
153
- writer.chars(chars);
154
- return buf.join('');
155
- }
156
-
157
-
158
- // Regular Expressions for parsing tags and attributes
159
- var START_TAG_REGEXP =
160
- /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,
161
- END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/,
162
- ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
163
- BEGIN_TAG_REGEXP = /^</,
164
- BEGING_END_TAGE_REGEXP = /^<\s*\//,
165
- COMMENT_REGEXP = /<!--(.*?)-->/g,
166
- DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
167
- CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
168
- // Match everything outside of normal chars and " (quote character)
169
- NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
170
-
171
-
172
- // Good source of info about elements and attributes
173
- // http://dev.w3.org/html5/spec/Overview.html#semantics
174
- // http://simon.html5.org/html-elements
175
-
176
- // Safe Void Elements - HTML5
177
- // http://dev.w3.org/html5/spec/Overview.html#void-elements
178
- var voidElements = makeMap("area,br,col,hr,img,wbr");
179
-
180
- // Elements that you can, intentionally, leave open (and which close themselves)
181
- // http://dev.w3.org/html5/spec/Overview.html#optional-tags
182
- var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
183
- optionalEndTagInlineElements = makeMap("rp,rt"),
184
- optionalEndTagElements = angular.extend({},
185
- optionalEndTagInlineElements,
186
- optionalEndTagBlockElements);
187
-
188
- // Safe Block Elements - HTML5
189
- var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
190
- "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
191
- "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
192
-
193
- // Inline Elements - HTML5
194
- var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
195
- "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
196
- "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
197
-
198
-
199
- // Special Elements (can contain anything)
200
- var specialElements = makeMap("script,style");
201
-
202
- var validElements = angular.extend({},
203
- voidElements,
204
- blockElements,
205
- inlineElements,
206
- optionalEndTagElements);
207
-
208
- //Attributes that have href and hence need to be sanitized
209
- var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap");
210
- var validAttrs = angular.extend({}, uriAttrs, makeMap(
211
- 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+
212
- 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+
213
- 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+
214
- 'scope,scrolling,shape,span,start,summary,target,title,type,'+
215
- 'valign,value,vspace,width'));
216
-
217
- function makeMap(str) {
218
- var obj = {}, items = str.split(','), i;
219
- for (i = 0; i < items.length; i++) obj[items[i]] = true;
220
- return obj;
221
- }
222
-
223
-
224
- /**
225
- * @example
226
- * htmlParser(htmlString, {
227
- * start: function(tag, attrs, unary) {},
228
- * end: function(tag) {},
229
- * chars: function(text) {},
230
- * comment: function(text) {}
231
- * });
232
- *
233
- * @param {string} html string
234
- * @param {object} handler
235
- */
236
- function htmlParser( html, handler ) {
237
- var index, chars, match, stack = [], last = html;
238
- stack.last = function() { return stack[ stack.length - 1 ]; };
239
-
240
- while ( html ) {
241
- chars = true;
242
-
243
- // Make sure we're not in a script or style element
244
- if ( !stack.last() || !specialElements[ stack.last() ] ) {
245
-
246
- // Comment
247
- if ( html.indexOf("<!--") === 0 ) {
248
- // comments containing -- are not allowed unless they terminate the comment
249
- index = html.indexOf("--", 4);
250
-
251
- if ( index >= 0 && html.lastIndexOf("-->", index) === index) {
252
- if (handler.comment) handler.comment( html.substring( 4, index ) );
253
- html = html.substring( index + 3 );
254
- chars = false;
255
- }
256
- // DOCTYPE
257
- } else if ( DOCTYPE_REGEXP.test(html) ) {
258
- match = html.match( DOCTYPE_REGEXP );
259
-
260
- if ( match ) {
261
- html = html.replace( match[0] , '');
262
- chars = false;
263
- }
264
- // end tag
265
- } else if ( BEGING_END_TAGE_REGEXP.test(html) ) {
266
- match = html.match( END_TAG_REGEXP );
267
-
268
- if ( match ) {
269
- html = html.substring( match[0].length );
270
- match[0].replace( END_TAG_REGEXP, parseEndTag );
271
- chars = false;
272
- }
273
-
274
- // start tag
275
- } else if ( BEGIN_TAG_REGEXP.test(html) ) {
276
- match = html.match( START_TAG_REGEXP );
277
-
278
- if ( match ) {
279
- html = html.substring( match[0].length );
280
- match[0].replace( START_TAG_REGEXP, parseStartTag );
281
- chars = false;
282
- }
283
- }
284
-
285
- if ( chars ) {
286
- index = html.indexOf("<");
287
-
288
- var text = index < 0 ? html : html.substring( 0, index );
289
- html = index < 0 ? "" : html.substring( index );
290
-
291
- if (handler.chars) handler.chars( decodeEntities(text) );
292
- }
293
-
294
- } else {
295
- html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
296
- function(all, text){
297
- text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1");
298
-
299
- if (handler.chars) handler.chars( decodeEntities(text) );
300
-
301
- return "";
302
- });
303
-
304
- parseEndTag( "", stack.last() );
305
- }
306
-
307
- if ( html == last ) {
308
- throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " +
309
- "of html: {0}", html);
310
- }
311
- last = html;
312
- }
313
-
314
- // Clean up any remaining tags
315
- parseEndTag();
316
-
317
- function parseStartTag( tag, tagName, rest, unary ) {
318
- tagName = angular.lowercase(tagName);
319
- if ( blockElements[ tagName ] ) {
320
- while ( stack.last() && inlineElements[ stack.last() ] ) {
321
- parseEndTag( "", stack.last() );
322
- }
323
- }
324
-
325
- if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) {
326
- parseEndTag( "", tagName );
327
- }
328
-
329
- unary = voidElements[ tagName ] || !!unary;
330
-
331
- if ( !unary )
332
- stack.push( tagName );
333
-
334
- var attrs = {};
335
-
336
- rest.replace(ATTR_REGEXP,
337
- function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {
338
- var value = doubleQuotedValue
339
- || singleQuotedValue
340
- || unquotedValue
341
- || '';
342
-
343
- attrs[name] = decodeEntities(value);
344
- });
345
- if (handler.start) handler.start( tagName, attrs, unary );
346
- }
347
-
348
- function parseEndTag( tag, tagName ) {
349
- var pos = 0, i;
350
- tagName = angular.lowercase(tagName);
351
- if ( tagName )
352
- // Find the closest opened tag of the same type
353
- for ( pos = stack.length - 1; pos >= 0; pos-- )
354
- if ( stack[ pos ] == tagName )
355
- break;
356
-
357
- if ( pos >= 0 ) {
358
- // Close all the open elements, up the stack
359
- for ( i = stack.length - 1; i >= pos; i-- )
360
- if (handler.end) handler.end( stack[ i ] );
361
-
362
- // Remove the open elements from the stack
363
- stack.length = pos;
364
- }
365
- }
366
- }
367
-
368
- var hiddenPre=document.createElement("pre");
369
- var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/;
370
- /**
371
- * decodes all entities into regular string
372
- * @param value
373
- * @returns {string} A string with decoded entities.
374
- */
375
- function decodeEntities(value) {
376
- if (!value) { return ''; }
377
-
378
- // Note: IE8 does not preserve spaces at the start/end of innerHTML
379
- // so we must capture them and reattach them afterward
380
- var parts = spaceRe.exec(value);
381
- var spaceBefore = parts[1];
382
- var spaceAfter = parts[3];
383
- var content = parts[2];
384
- if (content) {
385
- hiddenPre.innerHTML=content.replace(/</g,"&lt;");
386
- // innerText depends on styling as it doesn't display hidden elements.
387
- // Therefore, it's better to use textContent not to cause unnecessary
388
- // reflows. However, IE<9 don't support textContent so the innerText
389
- // fallback is necessary.
390
- content = 'textContent' in hiddenPre ?
391
- hiddenPre.textContent : hiddenPre.innerText;
392
- }
393
- return spaceBefore + content + spaceAfter;
394
- }
395
-
396
- /**
397
- * Escapes all potentially dangerous characters, so that the
398
- * resulting string can be safely inserted into attribute or
399
- * element text.
400
- * @param value
401
- * @returns escaped text
402
- */
403
- function encodeEntities(value) {
404
- return value.
405
- replace(/&/g, '&amp;').
406
- replace(NON_ALPHANUMERIC_REGEXP, function(value){
407
- return '&#' + value.charCodeAt(0) + ';';
408
- }).
409
- replace(/</g, '&lt;').
410
- replace(/>/g, '&gt;');
411
- }
412
-
413
- /**
414
- * create an HTML/XML writer which writes to buffer
415
- * @param {Array} buf use buf.jain('') to get out sanitized html string
416
- * @returns {object} in the form of {
417
- * start: function(tag, attrs, unary) {},
418
- * end: function(tag) {},
419
- * chars: function(text) {},
420
- * comment: function(text) {}
421
- * }
422
- */
423
- function htmlSanitizeWriter(buf, uriValidator){
424
- var ignore = false;
425
- var out = angular.bind(buf, buf.push);
426
- return {
427
- start: function(tag, attrs, unary){
428
- tag = angular.lowercase(tag);
429
- if (!ignore && specialElements[tag]) {
430
- ignore = tag;
431
- }
432
- if (!ignore && validElements[tag] === true) {
433
- out('<');
434
- out(tag);
435
- angular.forEach(attrs, function(value, key){
436
- var lkey=angular.lowercase(key);
437
- var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
438
- if (validAttrs[lkey] === true &&
439
- (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
440
- out(' ');
441
- out(key);
442
- out('="');
443
- out(encodeEntities(value));
444
- out('"');
445
- }
446
- });
447
- out(unary ? '/>' : '>');
448
- }
449
- },
450
- end: function(tag){
451
- tag = angular.lowercase(tag);
452
- if (!ignore && validElements[tag] === true) {
453
- out('</');
454
- out(tag);
455
- out('>');
456
- }
457
- if (tag == ignore) {
458
- ignore = false;
459
- }
460
- },
461
- chars: function(chars){
462
- if (!ignore) {
463
- out(encodeEntities(chars));
464
- }
465
- }
466
- };
467
- }
468
-
469
-
470
- // define ngSanitize module and register $sanitize service
471
- angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
472
-
473
- /* global sanitizeText: false */
474
-
475
- /**
476
- * @ngdoc filter
477
- * @name ngSanitize.filter:linky
478
- * @function
479
- *
480
- * @description
481
- * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
482
- * plain email address links.
483
- *
484
- * Requires the {@link ngSanitize `ngSanitize`} module to be installed.
485
- *
486
- * @param {string} text Input text.
487
- * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
488
- * @returns {string} Html-linkified text.
489
- *
490
- * @usage
491
- <span ng-bind-html="linky_expression | linky"></span>
492
- *
493
- * @example
494
- <doc:example module="ngSanitize">
495
- <doc:source>
496
- <script>
497
- function Ctrl($scope) {
498
- $scope.snippet =
499
- 'Pretty text with some links:\n'+
500
- 'http://angularjs.org/,\n'+
501
- 'mailto:us@somewhere.org,\n'+
502
- 'another@somewhere.org,\n'+
503
- 'and one more: ftp://127.0.0.1/.';
504
- $scope.snippetWithTarget = 'http://angularjs.org/';
505
- }
506
- </script>
507
- <div ng-controller="Ctrl">
508
- Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
509
- <table>
510
- <tr>
511
- <td>Filter</td>
512
- <td>Source</td>
513
- <td>Rendered</td>
514
- </tr>
515
- <tr id="linky-filter">
516
- <td>linky filter</td>
517
- <td>
518
- <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
519
- </td>
520
- <td>
521
- <div ng-bind-html="snippet | linky"></div>
522
- </td>
523
- </tr>
524
- <tr id="linky-target">
525
- <td>linky target</td>
526
- <td>
527
- <pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
528
- </td>
529
- <td>
530
- <div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
531
- </td>
532
- </tr>
533
- <tr id="escaped-html">
534
- <td>no filter</td>
535
- <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
536
- <td><div ng-bind="snippet"></div></td>
537
- </tr>
538
- </table>
539
- </doc:source>
540
- <doc:scenario>
541
- it('should linkify the snippet with urls', function() {
542
- expect(using('#linky-filter').binding('snippet | linky')).
543
- toBe('Pretty text with some links:&#10;' +
544
- '<a href="http://angularjs.org/">http://angularjs.org/</a>,&#10;' +
545
- '<a href="mailto:us@somewhere.org">us@somewhere.org</a>,&#10;' +
546
- '<a href="mailto:another@somewhere.org">another@somewhere.org</a>,&#10;' +
547
- 'and one more: <a href="ftp://127.0.0.1/">ftp://127.0.0.1/</a>.');
548
- });
549
-
550
- it ('should not linkify snippet without the linky filter', function() {
551
- expect(using('#escaped-html').binding('snippet')).
552
- toBe("Pretty text with some links:\n" +
553
- "http://angularjs.org/,\n" +
554
- "mailto:us@somewhere.org,\n" +
555
- "another@somewhere.org,\n" +
556
- "and one more: ftp://127.0.0.1/.");
557
- });
558
-
559
- it('should update', function() {
560
- input('snippet').enter('new http://link.');
561
- expect(using('#linky-filter').binding('snippet | linky')).
562
- toBe('new <a href="http://link">http://link</a>.');
563
- expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
564
- });
565
-
566
- it('should work with the target property', function() {
567
- expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")).
568
- toBe('<a target="_blank" href="http://angularjs.org/">http://angularjs.org/</a>');
569
- });
570
- </doc:scenario>
571
- </doc:example>
572
- */
573
- angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
574
- var LINKY_URL_REGEXP =
575
- /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/,
576
- MAILTO_REGEXP = /^mailto:/;
577
-
578
- return function(text, target) {
579
- if (!text) return text;
580
- var match;
581
- var raw = text;
582
- var html = [];
583
- var url;
584
- var i;
585
- while ((match = raw.match(LINKY_URL_REGEXP))) {
586
- // We can not end in these as they are sometimes found at the end of the sentence
587
- url = match[0];
588
- // if we did not match ftp/http/mailto then assume mailto
589
- if (match[2] == match[3]) url = 'mailto:' + url;
590
- i = match.index;
591
- addText(raw.substr(0, i));
592
- addLink(url, match[0].replace(MAILTO_REGEXP, ''));
593
- raw = raw.substring(i + match[0].length);
594
- }
595
- addText(raw);
596
- return $sanitize(html.join(''));
597
-
598
- function addText(text) {
599
- if (!text) {
600
- return;
601
- }
602
- html.push(sanitizeText(text));
603
- }
604
-
605
- function addLink(url, text) {
606
- html.push('<a ');
607
- if (angular.isDefined(target)) {
608
- html.push('target="');
609
- html.push(target);
610
- html.push('" ');
611
- }
612
- html.push('href="');
613
- html.push(url);
614
- html.push('">');
615
- addText(text);
616
- html.push('</a>');
617
- }
618
- };
619
- }]);
620
-
621
-
622
- })(window, window.angular);