rails-angularjs 1.3.16 → 1.4.0.pre.rc.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -13
  3. data/lib/rails-angularjs/version.rb +1 -2
  4. data/vendor/assets/javascripts/angular-animate.js +3231 -1885
  5. data/vendor/assets/javascripts/angular-animate.min.js +45 -29
  6. data/vendor/assets/javascripts/angular-animate.min.js.map +3 -3
  7. data/vendor/assets/javascripts/angular-aria.js +89 -75
  8. data/vendor/assets/javascripts/angular-aria.min.js +9 -9
  9. data/vendor/assets/javascripts/angular-aria.min.js.map +2 -2
  10. data/vendor/assets/javascripts/angular-cookies.js +255 -141
  11. data/vendor/assets/javascripts/angular-cookies.min.js +5 -4
  12. data/vendor/assets/javascripts/angular-cookies.min.js.map +3 -3
  13. data/vendor/assets/javascripts/angular-loader.js +41 -17
  14. data/vendor/assets/javascripts/angular-loader.min.js +5 -5
  15. data/vendor/assets/javascripts/angular-loader.min.js.map +2 -2
  16. data/vendor/assets/javascripts/{unstable/angular-messageFormat.js → angular-message-format.js} +76 -18
  17. data/vendor/assets/javascripts/angular-message-format.min.js +26 -0
  18. data/vendor/assets/javascripts/angular-message-format.min.js.map +8 -0
  19. data/vendor/assets/javascripts/angular-messages.js +430 -153
  20. data/vendor/assets/javascripts/angular-messages.min.js +7 -6
  21. data/vendor/assets/javascripts/angular-messages.min.js.map +3 -3
  22. data/vendor/assets/javascripts/angular-mocks.js +76 -92
  23. data/vendor/assets/javascripts/angular-resource.js +4 -4
  24. data/vendor/assets/javascripts/angular-resource.min.js +3 -3
  25. data/vendor/assets/javascripts/angular-resource.min.js.map +1 -1
  26. data/vendor/assets/javascripts/angular-route.js +8 -6
  27. data/vendor/assets/javascripts/angular-route.min.js +2 -2
  28. data/vendor/assets/javascripts/angular-route.min.js.map +1 -1
  29. data/vendor/assets/javascripts/angular-sanitize.js +32 -28
  30. data/vendor/assets/javascripts/angular-sanitize.min.js +11 -11
  31. data/vendor/assets/javascripts/angular-sanitize.min.js.map +2 -2
  32. data/vendor/assets/javascripts/angular-scenario.js +4155 -2553
  33. data/vendor/assets/javascripts/angular-touch.js +15 -12
  34. data/vendor/assets/javascripts/angular-touch.min.js +9 -9
  35. data/vendor/assets/javascripts/angular-touch.min.js.map +2 -2
  36. data/vendor/assets/javascripts/angular.js +4092 -2529
  37. data/vendor/assets/javascripts/angular.min.js +283 -247
  38. data/vendor/assets/javascripts/angular.min.js.map +3 -3
  39. metadata +8 -39
  40. data/vendor/assets/javascripts/unstable/angular-animate.js +0 -3268
  41. data/vendor/assets/javascripts/unstable/angular-animate.min.js +0 -49
  42. data/vendor/assets/javascripts/unstable/angular-animate.min.js.map +0 -8
  43. data/vendor/assets/javascripts/unstable/angular-aria.js +0 -377
  44. data/vendor/assets/javascripts/unstable/angular-aria.min.js +0 -13
  45. data/vendor/assets/javascripts/unstable/angular-aria.min.js.map +0 -8
  46. data/vendor/assets/javascripts/unstable/angular-cookies.js +0 -320
  47. data/vendor/assets/javascripts/unstable/angular-cookies.min.js +0 -9
  48. data/vendor/assets/javascripts/unstable/angular-cookies.min.js.map +0 -8
  49. data/vendor/assets/javascripts/unstable/angular-loader.js +0 -429
  50. data/vendor/assets/javascripts/unstable/angular-loader.min.js +0 -9
  51. data/vendor/assets/javascripts/unstable/angular-loader.min.js.map +0 -8
  52. data/vendor/assets/javascripts/unstable/angular-messageFormat.min.js +0 -26
  53. data/vendor/assets/javascripts/unstable/angular-messageFormat.min.js.map +0 -8
  54. data/vendor/assets/javascripts/unstable/angular-messages.js +0 -667
  55. data/vendor/assets/javascripts/unstable/angular-messages.min.js +0 -11
  56. data/vendor/assets/javascripts/unstable/angular-messages.min.js.map +0 -8
  57. data/vendor/assets/javascripts/unstable/angular-mocks.js +0 -2452
  58. data/vendor/assets/javascripts/unstable/angular-resource.js +0 -668
  59. data/vendor/assets/javascripts/unstable/angular-resource.min.js +0 -13
  60. data/vendor/assets/javascripts/unstable/angular-resource.min.js.map +0 -8
  61. data/vendor/assets/javascripts/unstable/angular-route.js +0 -991
  62. data/vendor/assets/javascripts/unstable/angular-route.min.js +0 -15
  63. data/vendor/assets/javascripts/unstable/angular-route.min.js.map +0 -8
  64. data/vendor/assets/javascripts/unstable/angular-sanitize.js +0 -683
  65. data/vendor/assets/javascripts/unstable/angular-sanitize.min.js +0 -16
  66. data/vendor/assets/javascripts/unstable/angular-sanitize.min.js.map +0 -8
  67. data/vendor/assets/javascripts/unstable/angular-scenario.js +0 -39082
  68. data/vendor/assets/javascripts/unstable/angular-touch.js +0 -625
  69. data/vendor/assets/javascripts/unstable/angular-touch.min.js +0 -13
  70. data/vendor/assets/javascripts/unstable/angular-touch.min.js.map +0 -8
  71. data/vendor/assets/javascripts/unstable/angular.js +0 -27674
  72. data/vendor/assets/javascripts/unstable/angular.min.js +0 -286
  73. data/vendor/assets/javascripts/unstable/angular.min.js.map +0 -8
@@ -1,683 +0,0 @@
1
- /**
2
- * @license AngularJS v1.4.0-rc.0
3
- * (c) 2010-2015 Google, Inc. http://angularjs.org
4
- * License: MIT
5
- */
6
- (function(window, angular, undefined) {'use strict';
7
-
8
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
9
- * Any commits to this file should be reviewed with security in mind. *
10
- * Changes to this file can potentially create security vulnerabilities. *
11
- * An approval from 2 Core members with history of modifying *
12
- * this file is required. *
13
- * *
14
- * Does the change somehow allow for arbitrary javascript to be executed? *
15
- * Or allows for someone to change the prototype of built-in objects? *
16
- * Or gives undesired access to variables likes document or window? *
17
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
18
-
19
- var $sanitizeMinErr = angular.$$minErr('$sanitize');
20
-
21
- /**
22
- * @ngdoc module
23
- * @name ngSanitize
24
- * @description
25
- *
26
- * # ngSanitize
27
- *
28
- * The `ngSanitize` module provides functionality to sanitize HTML.
29
- *
30
- *
31
- * <div doc-module-components="ngSanitize"></div>
32
- *
33
- * See {@link ngSanitize.$sanitize `$sanitize`} for usage.
34
- */
35
-
36
- /*
37
- * HTML Parser By Misko Hevery (misko@hevery.com)
38
- * based on: HTML Parser By John Resig (ejohn.org)
39
- * Original code by Erik Arvidsson, Mozilla Public License
40
- * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
41
- *
42
- * // Use like so:
43
- * htmlParser(htmlString, {
44
- * start: function(tag, attrs, unary) {},
45
- * end: function(tag) {},
46
- * chars: function(text) {},
47
- * comment: function(text) {}
48
- * });
49
- *
50
- */
51
-
52
-
53
- /**
54
- * @ngdoc service
55
- * @name $sanitize
56
- * @kind function
57
- *
58
- * @description
59
- * The input is sanitized by parsing the HTML into tokens. All safe tokens (from a whitelist) are
60
- * then serialized back to properly escaped html string. This means that no unsafe input can make
61
- * it into the returned string, however, since our parser is more strict than a typical browser
62
- * parser, it's possible that some obscure input, which would be recognized as valid HTML by a
63
- * browser, won't make it through the sanitizer. The input may also contain SVG markup.
64
- * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and
65
- * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}.
66
- *
67
- * @param {string} html HTML input.
68
- * @returns {string} Sanitized HTML.
69
- *
70
- * @example
71
- <example module="sanitizeExample" deps="angular-sanitize.js">
72
- <file name="index.html">
73
- <script>
74
- angular.module('sanitizeExample', ['ngSanitize'])
75
- .controller('ExampleController', ['$scope', '$sce', function($scope, $sce) {
76
- $scope.snippet =
77
- '<p style="color:blue">an html\n' +
78
- '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +
79
- 'snippet</p>';
80
- $scope.deliberatelyTrustDangerousSnippet = function() {
81
- return $sce.trustAsHtml($scope.snippet);
82
- };
83
- }]);
84
- </script>
85
- <div ng-controller="ExampleController">
86
- Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
87
- <table>
88
- <tr>
89
- <td>Directive</td>
90
- <td>How</td>
91
- <td>Source</td>
92
- <td>Rendered</td>
93
- </tr>
94
- <tr id="bind-html-with-sanitize">
95
- <td>ng-bind-html</td>
96
- <td>Automatically uses $sanitize</td>
97
- <td><pre>&lt;div ng-bind-html="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
98
- <td><div ng-bind-html="snippet"></div></td>
99
- </tr>
100
- <tr id="bind-html-with-trust">
101
- <td>ng-bind-html</td>
102
- <td>Bypass $sanitize by explicitly trusting the dangerous value</td>
103
- <td>
104
- <pre>&lt;div ng-bind-html="deliberatelyTrustDangerousSnippet()"&gt;
105
- &lt;/div&gt;</pre>
106
- </td>
107
- <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td>
108
- </tr>
109
- <tr id="bind-default">
110
- <td>ng-bind</td>
111
- <td>Automatically escapes</td>
112
- <td><pre>&lt;div ng-bind="snippet"&gt;<br/>&lt;/div&gt;</pre></td>
113
- <td><div ng-bind="snippet"></div></td>
114
- </tr>
115
- </table>
116
- </div>
117
- </file>
118
- <file name="protractor.js" type="protractor">
119
- it('should sanitize the html snippet by default', function() {
120
- expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
121
- toBe('<p>an html\n<em>click here</em>\nsnippet</p>');
122
- });
123
-
124
- it('should inline raw snippet if bound to a trusted value', function() {
125
- expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).
126
- toBe("<p style=\"color:blue\">an html\n" +
127
- "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +
128
- "snippet</p>");
129
- });
130
-
131
- it('should escape snippet without any filter', function() {
132
- expect(element(by.css('#bind-default div')).getInnerHtml()).
133
- toBe("&lt;p style=\"color:blue\"&gt;an html\n" +
134
- "&lt;em onmouseover=\"this.textContent='PWN3D!'\"&gt;click here&lt;/em&gt;\n" +
135
- "snippet&lt;/p&gt;");
136
- });
137
-
138
- it('should update', function() {
139
- element(by.model('snippet')).clear();
140
- element(by.model('snippet')).sendKeys('new <b onclick="alert(1)">text</b>');
141
- expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()).
142
- toBe('new <b>text</b>');
143
- expect(element(by.css('#bind-html-with-trust div')).getInnerHtml()).toBe(
144
- 'new <b onclick="alert(1)">text</b>');
145
- expect(element(by.css('#bind-default div')).getInnerHtml()).toBe(
146
- "new &lt;b onclick=\"alert(1)\"&gt;text&lt;/b&gt;");
147
- });
148
- </file>
149
- </example>
150
- */
151
- function $SanitizeProvider() {
152
- this.$get = ['$$sanitizeUri', function($$sanitizeUri) {
153
- return function(html) {
154
- var buf = [];
155
- htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) {
156
- return !/^unsafe/.test($$sanitizeUri(uri, isImage));
157
- }));
158
- return buf.join('');
159
- };
160
- }];
161
- }
162
-
163
- function sanitizeText(chars) {
164
- var buf = [];
165
- var writer = htmlSanitizeWriter(buf, angular.noop);
166
- writer.chars(chars);
167
- return buf.join('');
168
- }
169
-
170
-
171
- // Regular Expressions for parsing tags and attributes
172
- var START_TAG_REGEXP =
173
- /^<((?:[a-zA-Z])[\w:-]*)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*(>?)/,
174
- END_TAG_REGEXP = /^<\/\s*([\w:-]+)[^>]*>/,
175
- ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,
176
- BEGIN_TAG_REGEXP = /^</,
177
- BEGING_END_TAGE_REGEXP = /^<\//,
178
- COMMENT_REGEXP = /<!--(.*?)-->/g,
179
- DOCTYPE_REGEXP = /<!DOCTYPE([^>]*?)>/i,
180
- CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
181
- SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
182
- // Match everything outside of normal chars and " (quote character)
183
- NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;
184
-
185
-
186
- // Good source of info about elements and attributes
187
- // http://dev.w3.org/html5/spec/Overview.html#semantics
188
- // http://simon.html5.org/html-elements
189
-
190
- // Safe Void Elements - HTML5
191
- // http://dev.w3.org/html5/spec/Overview.html#void-elements
192
- var voidElements = makeMap("area,br,col,hr,img,wbr");
193
-
194
- // Elements that you can, intentionally, leave open (and which close themselves)
195
- // http://dev.w3.org/html5/spec/Overview.html#optional-tags
196
- var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),
197
- optionalEndTagInlineElements = makeMap("rp,rt"),
198
- optionalEndTagElements = angular.extend({},
199
- optionalEndTagInlineElements,
200
- optionalEndTagBlockElements);
201
-
202
- // Safe Block Elements - HTML5
203
- var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
204
- "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
205
- "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
206
-
207
- // Inline Elements - HTML5
208
- var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
209
- "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
210
- "samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
211
-
212
- // SVG Elements
213
- // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Elements
214
- // Note: the elements animate,animateColor,animateMotion,animateTransform,set are intentionally omitted.
215
- // They can potentially allow for arbitrary javascript to be executed. See #11290
216
- var svgElements = makeMap("circle,defs,desc,ellipse,font-face,font-face-name,font-face-src,g,glyph," +
217
- "hkern,image,linearGradient,line,marker,metadata,missing-glyph,mpath,path,polygon,polyline," +
218
- "radialGradient,rect,stop,svg,switch,text,title,tspan,use");
219
-
220
- // Special Elements (can contain anything)
221
- var specialElements = makeMap("script,style");
222
-
223
- var validElements = angular.extend({},
224
- voidElements,
225
- blockElements,
226
- inlineElements,
227
- optionalEndTagElements,
228
- svgElements);
229
-
230
- //Attributes that have href and hence need to be sanitized
231
- var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap,xlink:href");
232
-
233
- var htmlAttrs = makeMap('abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' +
234
- 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' +
235
- 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' +
236
- 'scope,scrolling,shape,size,span,start,summary,target,title,type,' +
237
- 'valign,value,vspace,width');
238
-
239
- // SVG attributes (without "id" and "name" attributes)
240
- // https://wiki.whatwg.org/wiki/Sanitization_rules#svg_Attributes
241
- var svgAttrs = makeMap('accent-height,accumulate,additive,alphabetic,arabic-form,ascent,' +
242
- 'baseProfile,bbox,begin,by,calcMode,cap-height,class,color,color-rendering,content,' +
243
- 'cx,cy,d,dx,dy,descent,display,dur,end,fill,fill-rule,font-family,font-size,font-stretch,' +
244
- 'font-style,font-variant,font-weight,from,fx,fy,g1,g2,glyph-name,gradientUnits,hanging,' +
245
- 'height,horiz-adv-x,horiz-origin-x,ideographic,k,keyPoints,keySplines,keyTimes,lang,' +
246
- 'marker-end,marker-mid,marker-start,markerHeight,markerUnits,markerWidth,mathematical,' +
247
- 'max,min,offset,opacity,orient,origin,overline-position,overline-thickness,panose-1,' +
248
- 'path,pathLength,points,preserveAspectRatio,r,refX,refY,repeatCount,repeatDur,' +
249
- 'requiredExtensions,requiredFeatures,restart,rotate,rx,ry,slope,stemh,stemv,stop-color,' +
250
- 'stop-opacity,strikethrough-position,strikethrough-thickness,stroke,stroke-dasharray,' +
251
- 'stroke-dashoffset,stroke-linecap,stroke-linejoin,stroke-miterlimit,stroke-opacity,' +
252
- 'stroke-width,systemLanguage,target,text-anchor,to,transform,type,u1,u2,underline-position,' +
253
- 'underline-thickness,unicode,unicode-range,units-per-em,values,version,viewBox,visibility,' +
254
- 'width,widths,x,x-height,x1,x2,xlink:actuate,xlink:arcrole,xlink:role,xlink:show,xlink:title,' +
255
- 'xlink:type,xml:base,xml:lang,xml:space,xmlns,xmlns:xlink,y,y1,y2,zoomAndPan', true);
256
-
257
- var validAttrs = angular.extend({},
258
- uriAttrs,
259
- svgAttrs,
260
- htmlAttrs);
261
-
262
- function makeMap(str, lowercaseKeys) {
263
- var obj = {}, items = str.split(','), i;
264
- for (i = 0; i < items.length; i++) {
265
- obj[lowercaseKeys ? angular.lowercase(items[i]) : items[i]] = true;
266
- }
267
- return obj;
268
- }
269
-
270
-
271
- /**
272
- * @example
273
- * htmlParser(htmlString, {
274
- * start: function(tag, attrs, unary) {},
275
- * end: function(tag) {},
276
- * chars: function(text) {},
277
- * comment: function(text) {}
278
- * });
279
- *
280
- * @param {string} html string
281
- * @param {object} handler
282
- */
283
- function htmlParser(html, handler) {
284
- if (typeof html !== 'string') {
285
- if (html === null || typeof html === 'undefined') {
286
- html = '';
287
- } else {
288
- html = '' + html;
289
- }
290
- }
291
- var index, chars, match, stack = [], last = html, text;
292
- stack.last = function() { return stack[stack.length - 1]; };
293
-
294
- while (html) {
295
- text = '';
296
- chars = true;
297
-
298
- // Make sure we're not in a script or style element
299
- if (!stack.last() || !specialElements[stack.last()]) {
300
-
301
- // Comment
302
- if (html.indexOf("<!--") === 0) {
303
- // comments containing -- are not allowed unless they terminate the comment
304
- index = html.indexOf("--", 4);
305
-
306
- if (index >= 0 && html.lastIndexOf("-->", index) === index) {
307
- if (handler.comment) handler.comment(html.substring(4, index));
308
- html = html.substring(index + 3);
309
- chars = false;
310
- }
311
- // DOCTYPE
312
- } else if (DOCTYPE_REGEXP.test(html)) {
313
- match = html.match(DOCTYPE_REGEXP);
314
-
315
- if (match) {
316
- html = html.replace(match[0], '');
317
- chars = false;
318
- }
319
- // end tag
320
- } else if (BEGING_END_TAGE_REGEXP.test(html)) {
321
- match = html.match(END_TAG_REGEXP);
322
-
323
- if (match) {
324
- html = html.substring(match[0].length);
325
- match[0].replace(END_TAG_REGEXP, parseEndTag);
326
- chars = false;
327
- }
328
-
329
- // start tag
330
- } else if (BEGIN_TAG_REGEXP.test(html)) {
331
- match = html.match(START_TAG_REGEXP);
332
-
333
- if (match) {
334
- // We only have a valid start-tag if there is a '>'.
335
- if (match[4]) {
336
- html = html.substring(match[0].length);
337
- match[0].replace(START_TAG_REGEXP, parseStartTag);
338
- }
339
- chars = false;
340
- } else {
341
- // no ending tag found --- this piece should be encoded as an entity.
342
- text += '<';
343
- html = html.substring(1);
344
- }
345
- }
346
-
347
- if (chars) {
348
- index = html.indexOf("<");
349
-
350
- text += index < 0 ? html : html.substring(0, index);
351
- html = index < 0 ? "" : html.substring(index);
352
-
353
- if (handler.chars) handler.chars(decodeEntities(text));
354
- }
355
-
356
- } else {
357
- // IE versions 9 and 10 do not understand the regex '[^]', so using a workaround with [\W\w].
358
- html = html.replace(new RegExp("([\\W\\w]*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'),
359
- function(all, text) {
360
- text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1");
361
-
362
- if (handler.chars) handler.chars(decodeEntities(text));
363
-
364
- return "";
365
- });
366
-
367
- parseEndTag("", stack.last());
368
- }
369
-
370
- if (html == last) {
371
- throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " +
372
- "of html: {0}", html);
373
- }
374
- last = html;
375
- }
376
-
377
- // Clean up any remaining tags
378
- parseEndTag();
379
-
380
- function parseStartTag(tag, tagName, rest, unary) {
381
- tagName = angular.lowercase(tagName);
382
- if (blockElements[tagName]) {
383
- while (stack.last() && inlineElements[stack.last()]) {
384
- parseEndTag("", stack.last());
385
- }
386
- }
387
-
388
- if (optionalEndTagElements[tagName] && stack.last() == tagName) {
389
- parseEndTag("", tagName);
390
- }
391
-
392
- unary = voidElements[tagName] || !!unary;
393
-
394
- if (!unary) {
395
- stack.push(tagName);
396
- }
397
-
398
- var attrs = {};
399
-
400
- rest.replace(ATTR_REGEXP,
401
- function(match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) {
402
- var value = doubleQuotedValue
403
- || singleQuotedValue
404
- || unquotedValue
405
- || '';
406
-
407
- attrs[name] = decodeEntities(value);
408
- });
409
- if (handler.start) handler.start(tagName, attrs, unary);
410
- }
411
-
412
- function parseEndTag(tag, tagName) {
413
- var pos = 0, i;
414
- tagName = angular.lowercase(tagName);
415
- if (tagName) {
416
- // Find the closest opened tag of the same type
417
- for (pos = stack.length - 1; pos >= 0; pos--) {
418
- if (stack[pos] == tagName) break;
419
- }
420
- }
421
-
422
- if (pos >= 0) {
423
- // Close all the open elements, up the stack
424
- for (i = stack.length - 1; i >= pos; i--)
425
- if (handler.end) handler.end(stack[i]);
426
-
427
- // Remove the open elements from the stack
428
- stack.length = pos;
429
- }
430
- }
431
- }
432
-
433
- var hiddenPre=document.createElement("pre");
434
- /**
435
- * decodes all entities into regular string
436
- * @param value
437
- * @returns {string} A string with decoded entities.
438
- */
439
- function decodeEntities(value) {
440
- if (!value) { return ''; }
441
-
442
- hiddenPre.innerHTML = value.replace(/</g,"&lt;");
443
- // innerText depends on styling as it doesn't display hidden elements.
444
- // Therefore, it's better to use textContent not to cause unnecessary reflows.
445
- return hiddenPre.textContent;
446
- }
447
-
448
- /**
449
- * Escapes all potentially dangerous characters, so that the
450
- * resulting string can be safely inserted into attribute or
451
- * element text.
452
- * @param value
453
- * @returns {string} escaped text
454
- */
455
- function encodeEntities(value) {
456
- return value.
457
- replace(/&/g, '&amp;').
458
- replace(SURROGATE_PAIR_REGEXP, function(value) {
459
- var hi = value.charCodeAt(0);
460
- var low = value.charCodeAt(1);
461
- return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
462
- }).
463
- replace(NON_ALPHANUMERIC_REGEXP, function(value) {
464
- return '&#' + value.charCodeAt(0) + ';';
465
- }).
466
- replace(/</g, '&lt;').
467
- replace(/>/g, '&gt;');
468
- }
469
-
470
- /**
471
- * create an HTML/XML writer which writes to buffer
472
- * @param {Array} buf use buf.jain('') to get out sanitized html string
473
- * @returns {object} in the form of {
474
- * start: function(tag, attrs, unary) {},
475
- * end: function(tag) {},
476
- * chars: function(text) {},
477
- * comment: function(text) {}
478
- * }
479
- */
480
- function htmlSanitizeWriter(buf, uriValidator) {
481
- var ignore = false;
482
- var out = angular.bind(buf, buf.push);
483
- return {
484
- start: function(tag, attrs, unary) {
485
- tag = angular.lowercase(tag);
486
- if (!ignore && specialElements[tag]) {
487
- ignore = tag;
488
- }
489
- if (!ignore && validElements[tag] === true) {
490
- out('<');
491
- out(tag);
492
- angular.forEach(attrs, function(value, key) {
493
- var lkey=angular.lowercase(key);
494
- var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background');
495
- if (validAttrs[lkey] === true &&
496
- (uriAttrs[lkey] !== true || uriValidator(value, isImage))) {
497
- out(' ');
498
- out(key);
499
- out('="');
500
- out(encodeEntities(value));
501
- out('"');
502
- }
503
- });
504
- out(unary ? '/>' : '>');
505
- }
506
- },
507
- end: function(tag) {
508
- tag = angular.lowercase(tag);
509
- if (!ignore && validElements[tag] === true) {
510
- out('</');
511
- out(tag);
512
- out('>');
513
- }
514
- if (tag == ignore) {
515
- ignore = false;
516
- }
517
- },
518
- chars: function(chars) {
519
- if (!ignore) {
520
- out(encodeEntities(chars));
521
- }
522
- }
523
- };
524
- }
525
-
526
-
527
- // define ngSanitize module and register $sanitize service
528
- angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider);
529
-
530
- /* global sanitizeText: false */
531
-
532
- /**
533
- * @ngdoc filter
534
- * @name linky
535
- * @kind function
536
- *
537
- * @description
538
- * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and
539
- * plain email address links.
540
- *
541
- * Requires the {@link ngSanitize `ngSanitize`} module to be installed.
542
- *
543
- * @param {string} text Input text.
544
- * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
545
- * @returns {string} Html-linkified text.
546
- *
547
- * @usage
548
- <span ng-bind-html="linky_expression | linky"></span>
549
- *
550
- * @example
551
- <example module="linkyExample" deps="angular-sanitize.js">
552
- <file name="index.html">
553
- <script>
554
- angular.module('linkyExample', ['ngSanitize'])
555
- .controller('ExampleController', ['$scope', function($scope) {
556
- $scope.snippet =
557
- 'Pretty text with some links:\n'+
558
- 'http://angularjs.org/,\n'+
559
- 'mailto:us@somewhere.org,\n'+
560
- 'another@somewhere.org,\n'+
561
- 'and one more: ftp://127.0.0.1/.';
562
- $scope.snippetWithTarget = 'http://angularjs.org/';
563
- }]);
564
- </script>
565
- <div ng-controller="ExampleController">
566
- Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>
567
- <table>
568
- <tr>
569
- <td>Filter</td>
570
- <td>Source</td>
571
- <td>Rendered</td>
572
- </tr>
573
- <tr id="linky-filter">
574
- <td>linky filter</td>
575
- <td>
576
- <pre>&lt;div ng-bind-html="snippet | linky"&gt;<br>&lt;/div&gt;</pre>
577
- </td>
578
- <td>
579
- <div ng-bind-html="snippet | linky"></div>
580
- </td>
581
- </tr>
582
- <tr id="linky-target">
583
- <td>linky target</td>
584
- <td>
585
- <pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
586
- </td>
587
- <td>
588
- <div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
589
- </td>
590
- </tr>
591
- <tr id="escaped-html">
592
- <td>no filter</td>
593
- <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
594
- <td><div ng-bind="snippet"></div></td>
595
- </tr>
596
- </table>
597
- </file>
598
- <file name="protractor.js" type="protractor">
599
- it('should linkify the snippet with urls', function() {
600
- expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
601
- toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' +
602
- 'another@somewhere.org, and one more: ftp://127.0.0.1/.');
603
- expect(element.all(by.css('#linky-filter a')).count()).toEqual(4);
604
- });
605
-
606
- it('should not linkify snippet without the linky filter', function() {
607
- expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()).
608
- toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' +
609
- 'another@somewhere.org, and one more: ftp://127.0.0.1/.');
610
- expect(element.all(by.css('#escaped-html a')).count()).toEqual(0);
611
- });
612
-
613
- it('should update', function() {
614
- element(by.model('snippet')).clear();
615
- element(by.model('snippet')).sendKeys('new http://link.');
616
- expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()).
617
- toBe('new http://link.');
618
- expect(element.all(by.css('#linky-filter a')).count()).toEqual(1);
619
- expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText())
620
- .toBe('new http://link.');
621
- });
622
-
623
- it('should work with the target property', function() {
624
- expect(element(by.id('linky-target')).
625
- element(by.binding("snippetWithTarget | linky:'_blank'")).getText()).
626
- toBe('http://angularjs.org/');
627
- expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank');
628
- });
629
- </file>
630
- </example>
631
- */
632
- angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
633
- var LINKY_URL_REGEXP =
634
- /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/,
635
- MAILTO_REGEXP = /^mailto:/;
636
-
637
- return function(text, target) {
638
- if (!text) return text;
639
- var match;
640
- var raw = text;
641
- var html = [];
642
- var url;
643
- var i;
644
- while ((match = raw.match(LINKY_URL_REGEXP))) {
645
- // We can not end in these as they are sometimes found at the end of the sentence
646
- url = match[0];
647
- // if we did not match ftp/http/www/mailto then assume mailto
648
- if (!match[2] && !match[4]) {
649
- url = (match[3] ? 'http://' : 'mailto:') + url;
650
- }
651
- i = match.index;
652
- addText(raw.substr(0, i));
653
- addLink(url, match[0].replace(MAILTO_REGEXP, ''));
654
- raw = raw.substring(i + match[0].length);
655
- }
656
- addText(raw);
657
- return $sanitize(html.join(''));
658
-
659
- function addText(text) {
660
- if (!text) {
661
- return;
662
- }
663
- html.push(sanitizeText(text));
664
- }
665
-
666
- function addLink(url, text) {
667
- html.push('<a ');
668
- if (angular.isDefined(target)) {
669
- html.push('target="',
670
- target,
671
- '" ');
672
- }
673
- html.push('href="',
674
- url.replace(/"/g, '&quot;'),
675
- '">');
676
- addText(text);
677
- html.push('</a>');
678
- }
679
- };
680
- }]);
681
-
682
-
683
- })(window, window.angular);