closure 1.3.1 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. data/README.md +142 -9
  2. data/bin/closure-script +19 -0
  3. data/closure-compiler/README +18 -4
  4. data/closure-compiler/compiler.jar +0 -0
  5. data/closure-templates/SoyToJsSrcCompiler.jar +0 -0
  6. data/closure-templates/soydata.js +163 -0
  7. data/closure-templates/soyutils.js +1191 -159
  8. data/closure-templates/soyutils_usegoog.js +1107 -60
  9. data/docs/closure/Closure.html +58 -52
  10. data/docs/closure/Closure/BeanShell.html +6 -3
  11. data/docs/closure/Closure/Compiler.html +18 -15
  12. data/docs/closure/Closure/Compiler/Compilation.html +9 -3
  13. data/docs/closure/Closure/Compiler/Error.html +3 -3
  14. data/docs/closure/Closure/FileResponse.html +13 -7
  15. data/docs/closure/Closure/Goog.html +49 -85
  16. data/docs/closure/Closure/Middleware.html +5 -3
  17. data/docs/closure/Closure/Script.html +14 -5
  18. data/docs/closure/Closure/Script/NotFound.html +3 -3
  19. data/docs/closure/Closure/Script/RenderStackOverflow.html +3 -3
  20. data/docs/closure/Closure/Server.html +6 -3
  21. data/docs/closure/Closure/ShowExceptions.html +5 -3
  22. data/docs/closure/Closure/Sources.html +145 -37
  23. data/docs/closure/Closure/Templates.html +11 -10
  24. data/docs/closure/Closure/Templates/Error.html +3 -3
  25. data/docs/closure/_index.html +4 -4
  26. data/docs/closure/css/full_list.css +2 -0
  27. data/docs/closure/css/style.css +2 -0
  28. data/docs/closure/file.LICENSE.html +3 -3
  29. data/docs/closure/file.README.html +151 -10
  30. data/docs/closure/frames.html +1 -1
  31. data/docs/closure/index.html +151 -10
  32. data/docs/closure/js/full_list.js +23 -6
  33. data/docs/closure/method_list.html +91 -83
  34. data/docs/closure/top-level-namespace.html +3 -3
  35. data/lib/closure.rb +3 -16
  36. data/lib/closure/compiler.rb +135 -53
  37. data/lib/closure/goog.rb +5 -29
  38. data/lib/closure/sources.rb +22 -9
  39. data/lib/closure/version.rb +1 -1
  40. data/scripts/config.ru +0 -1
  41. data/scripts/hello/compiler_build.js +5 -5
  42. data/scripts/hello/compiler_build.map +518 -522
  43. data/scripts/hello/compiler_debug.js +7 -13
  44. data/scripts/hello/legume.js +2 -2
  45. data/scripts/index.erb +0 -3
  46. data/scripts/modules/compiler_build.js +3 -3
  47. data/scripts/modules/compiler_build.map +11569 -11476
  48. data/scripts/modules/compiler_build_api.js +1 -1
  49. data/scripts/modules/compiler_build_app.js +71 -70
  50. data/scripts/modules/compiler_build_settings.js +2 -2
  51. data/scripts/modules/compiler_debug.js +3 -3
  52. data/scripts/modules/compiler_debug_api.js +2 -2
  53. data/scripts/modules/compiler_debug_app.js +926 -1382
  54. data/scripts/modules/compiler_debug_settings.js +21 -24
  55. metadata +8 -18
  56. data/externs/chrome_extensions.externs +0 -968
  57. data/externs/jquery-1.3.2.externs +0 -718
  58. data/externs/jquery-1.4.3.externs +0 -1289
  59. data/externs/jquery-1.4.4.externs +0 -1302
  60. data/externs/jquery-1.5.externs +0 -1697
  61. data/externs/jquery-ui.externs +0 -10
  62. data/externs/jquery.externs +0 -4
  63. data/scripts/jquery/compiler.js.erb +0 -7
  64. data/scripts/jquery/compiler_out.js +0 -1
  65. data/scripts/jquery/index.erb +0 -25
  66. data/scripts/jquery/jquery_1.4.4.js +0 -167
  67. data/scripts/jquery/jquery_test.js +0 -8
@@ -14,26 +14,40 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- // Utility functions and classes for Soy.
18
- //
19
- // The top portion of this file contains utilities for Soy users:
20
- // + soy.StringBuilder: Compatible with the 'stringbuilder' code style.
21
- // + soy.renderElement: Render template and set as innerHTML of an element.
22
- // + soy.renderAsFragment: Render template and return as HTML fragment.
23
- //
24
- // The bottom portion of this file contains utilities that should only be called
25
- // by Soy-generated JS code. Please do not use these functions directly from
26
- // your hand-writen code. Their names all start with '$$'.
17
+ /**
18
+ * @fileoverview
19
+ * Utility functions and classes for Soy.
20
+ *
21
+ * <p>
22
+ * The top portion of this file contains utilities for Soy users:<ul>
23
+ * <li> soy.StringBuilder: Compatible with the 'stringbuilder' code style.
24
+ * <li> soy.renderElement: Render template and set as innerHTML of an element.
25
+ * <li> soy.renderAsFragment: Render template and return as HTML fragment.
26
+ * </ul>
27
+ *
28
+ * <p>
29
+ * The bottom portion of this file contains utilities that should only be called
30
+ * by Soy-generated JS code. Please do not use these functions directly from
31
+ * your hand-writen code. Their names all start with '$$'.
32
+ *
33
+ * @author Mike Samuel
34
+ * @author Kai Huang
35
+ * @author Aharon Lenin
36
+ */
27
37
 
28
38
  goog.provide('soy');
29
39
  goog.provide('soy.StringBuilder');
40
+ goog.provide('soy.esc');
30
41
 
31
- goog.require('goog.dom');
42
+ goog.require('goog.asserts');
43
+ goog.require('goog.dom.DomHelper');
32
44
  goog.require('goog.format');
33
45
  goog.require('goog.i18n.BidiFormatter');
34
46
  goog.require('goog.i18n.bidi');
47
+ goog.require('goog.soy');
35
48
  goog.require('goog.string');
36
49
  goog.require('goog.string.StringBuffer');
50
+ goog.require('soydata');
37
51
 
38
52
 
39
53
  // -----------------------------------------------------------------------------
@@ -62,27 +76,62 @@ soy.StringBuilder = goog.string.StringBuffer;
62
76
  * instead of directly setting innerHTML in your hand-written code, so that it
63
77
  * will be easier to audit the code for cross-site scripting vulnerabilities.
64
78
  *
79
+ * NOTE: New code should consider using goog.soy.renderElement instead.
80
+ *
65
81
  * @param {Element} element The element whose content we are rendering.
66
82
  * @param {Function} template The Soy template defining the element's content.
67
83
  * @param {Object=} opt_templateData The data for the template.
84
+ * @param {Object=} opt_injectedData The injected data for the template.
68
85
  */
69
- soy.renderElement = function(element, template, opt_templateData) {
70
- element.innerHTML = template(opt_templateData);
71
- };
86
+ soy.renderElement = goog.soy.renderElement;
72
87
 
73
88
 
74
89
  /**
75
90
  * Helper function to render a Soy template into a single node or a document
76
91
  * fragment. If the rendered HTML string represents a single node, then that
77
- * node is returned. Otherwise a document fragment is returned containing the
92
+ * node is returned (note that this is *not* a fragment, despite them name of
93
+ * the method). Otherwise a document fragment is returned containing the
78
94
  * rendered nodes.
79
95
  *
96
+ * NOTE: New code should consider using goog.soy.renderAsFragment
97
+ * instead (note that the arguments are different).
98
+ *
99
+ * @param {Function} template The Soy template defining the element's content.
100
+ * @param {Object=} opt_templateData The data for the template.
101
+ * @param {Document=} opt_document The document used to create DOM nodes. If not
102
+ * specified, global document object is used.
103
+ * @param {Object=} opt_injectedData The injected data for the template.
104
+ * @return {!Node} The resulting node or document fragment.
105
+ */
106
+ soy.renderAsFragment = function(
107
+ template, opt_templateData, opt_document, opt_injectedData) {
108
+ return goog.soy.renderAsFragment(
109
+ template, opt_templateData, opt_injectedData,
110
+ new goog.dom.DomHelper(opt_document));
111
+ };
112
+
113
+
114
+ /**
115
+ * Helper function to render a Soy template into a single node. If the rendered
116
+ * HTML string represents a single node, then that node is returned. Otherwise,
117
+ * a DIV element is returned containing the rendered nodes.
118
+ *
119
+ * NOTE: New code should consider using goog.soy.renderAsElement
120
+ * instead (note that the arguments are different).
121
+ *
80
122
  * @param {Function} template The Soy template defining the element's content.
81
123
  * @param {Object=} opt_templateData The data for the template.
82
- * @return {Node} The resulting node or document fragment.
124
+ * @param {Document=} opt_document The document used to create DOM nodes. If not
125
+ * specified, global document object is used.
126
+ * @param {Object=} opt_injectedData The injected data for the template.
127
+ * @return {!Element} Rendered template contents, wrapped in a parent DIV
128
+ * element if necessary.
83
129
  */
84
- soy.renderAsFragment = function(template, opt_templateData) {
85
- return goog.dom.htmlToDocumentFragment(template(opt_templateData));
130
+ soy.renderAsElement = function(
131
+ template, opt_templateData, opt_document, opt_injectedData) {
132
+ return goog.soy.renderAsElement(
133
+ template, opt_templateData, opt_injectedData,
134
+ new goog.dom.DomHelper(opt_document));
86
135
  };
87
136
 
88
137
 
@@ -107,9 +156,9 @@ soy.$$augmentData = function(origData, additionalParams) {
107
156
 
108
157
  // Create a new object whose '__proto__' field is set to origData.
109
158
  /** @constructor */
110
- function tempCtor() {};
111
- tempCtor.prototype = origData;
112
- var newData = new tempCtor();
159
+ function TempCtor() {}
160
+ TempCtor.prototype = origData;
161
+ var newData = new TempCtor();
113
162
 
114
163
  // Add the additional params to the new object.
115
164
  for (var key in additionalParams) {
@@ -121,45 +170,462 @@ soy.$$augmentData = function(origData, additionalParams) {
121
170
 
122
171
 
123
172
  /**
124
- * Escapes HTML special characters in a string. Escapes double quote '"' in
173
+ * Gets the keys in a map as an array. There are no guarantees on the order.
174
+ * @param {Object} map The map to get the keys of.
175
+ * @return {Array.<string>} The array of keys in the given map.
176
+ */
177
+ soy.$$getMapKeys = function(map) {
178
+ var mapKeys = [];
179
+ for (var key in map) {
180
+ mapKeys.push(key);
181
+ }
182
+ return mapKeys;
183
+ };
184
+
185
+
186
+ /**
187
+ * Gets a consistent unique id for the given delegate template name. Two calls
188
+ * to this function will return the same id if and only if the input names are
189
+ * the same.
190
+ *
191
+ * <p> Important: This function must always be called with a string constant.
192
+ *
193
+ * <p> If Closure Compiler is not being used, then this is just this identity
194
+ * function. If Closure Compiler is being used, then each call to this function
195
+ * will be replaced with a short string constant, which will be consistent per
196
+ * input name.
197
+ *
198
+ * @param {string} delTemplateName The delegate template name for which to get a
199
+ * consistent unique id.
200
+ * @return {string} A unique id that is consistent per input name.
201
+ *
202
+ * @consistentIdGenerator
203
+ */
204
+ soy.$$getDelegateId = function(delTemplateName) {
205
+ return delTemplateName;
206
+ };
207
+
208
+
209
+ /**
210
+ * Map from registered delegate template id/name to the priority of the
211
+ * implementation.
212
+ * @type {Object}
213
+ * @private
214
+ */
215
+ soy.$$DELEGATE_REGISTRY_PRIORITIES_ = {};
216
+
217
+ /**
218
+ * Map from registered delegate template id/name to the implementation function.
219
+ * @type {Object}
220
+ * @private
221
+ */
222
+ soy.$$DELEGATE_REGISTRY_FUNCTIONS_ = {};
223
+
224
+
225
+ /**
226
+ * Registers a delegate implementation. If the same delegate template id/name
227
+ * has been registered previously, then priority values are compared and only
228
+ * the higher priority implementation is stored (if priorities are equal, an
229
+ * error is thrown).
230
+ *
231
+ * @param {string} delTemplateId The delegate template id/name to register.
232
+ * @param {number} delPriority The implementation's priority value.
233
+ * @param {Function} delFn The implementation function.
234
+ */
235
+ soy.$$registerDelegateFn = function(delTemplateId, delPriority, delFn) {
236
+ var mapKey = 'key_' + delTemplateId;
237
+ var currPriority = soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey];
238
+ if (currPriority === undefined || delPriority > currPriority) {
239
+ // Registering new or higher-priority function: replace registry entry.
240
+ soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey] = delPriority;
241
+ soy.$$DELEGATE_REGISTRY_FUNCTIONS_[mapKey] = delFn;
242
+ } else if (delPriority == currPriority) {
243
+ // Registering same-priority function: error.
244
+ throw Error(
245
+ 'Encountered two active delegates with same priority (id/name "' +
246
+ delTemplateId + '").');
247
+ } else {
248
+ // Registering lower-priority function: do nothing.
249
+ }
250
+ };
251
+
252
+
253
+ /**
254
+ * Retrieves the (highest-priority) implementation that has been registered for
255
+ * a given delegate template id/name. If no implementation has been registered
256
+ * for the id/name, then returns an implementation that is equivalent to an
257
+ * empty template (i.e. rendered output would be empty string).
258
+ *
259
+ * @param {string} delTemplateId The delegate template id/name to get.
260
+ * @return {Function} The retrieved implementation function.
261
+ */
262
+ soy.$$getDelegateFn = function(delTemplateId) {
263
+ var delFn = soy.$$DELEGATE_REGISTRY_FUNCTIONS_['key_' + delTemplateId];
264
+ return delFn ? delFn : soy.$$EMPTY_TEMPLATE_FN_;
265
+ };
266
+
267
+
268
+ /**
269
+ * Private helper soy.$$getDelegateFn(). This is the empty template function
270
+ * that is returned whenever there's no delegate implementation found.
271
+ *
272
+ * @param {Object.<string, *>=} opt_data
273
+ * @param {soy.StringBuilder=} opt_sb
274
+ * @param {Object.<string, *>=} opt_ijData
275
+ * @return {string}
276
+ * @private
277
+ */
278
+ soy.$$EMPTY_TEMPLATE_FN_ = function(opt_data, opt_sb, opt_ijData) {
279
+ return '';
280
+ };
281
+
282
+
283
+ /**
284
+ * Used for temporary fix. See GenJsCodeVisitor.java.
285
+ * TODO: Remove when i18n plurals team provides a better # processing option.
286
+ * @param {string} str The string to escape.
287
+ * @return {string} The escaped string.
288
+ */
289
+ soy.$$tempHashEscape = function(str) {
290
+ return str.replace(soy.$$HASH_RE_, '__HashLit__');
291
+ };
292
+
293
+ /**
294
+ * Used by soy.$$tempHashEscape().
295
+ * @type {RegExp}
296
+ * @private
297
+ */
298
+ soy.$$HASH_RE_ = /#/g;
299
+
300
+
301
+ /**
302
+ * Used for temporary fix. See GenJsCodeVisitor.java.
303
+ * TODO: Remove when i18n plurals team provides a better # processing option.
304
+ * @param {string} str The string to unescape.
305
+ * @return {string} The unescaped string.
306
+ */
307
+ soy.$$tempHashUnescape = function(str) {
308
+ return str.replace(soy.$$HASH_ESCAPED_RE_, '#');
309
+ };
310
+
311
+ /**
312
+ * Used by soy.$$tempHashUnescape().
313
+ * @type {RegExp}
314
+ * @private
315
+ */
316
+ soy.$$HASH_ESCAPED_RE_ = /__HashLit__/g;
317
+
318
+
319
+ // -----------------------------------------------------------------------------
320
+ // Escape/filter/normalize.
321
+
322
+
323
+ /**
324
+ * Escapes HTML special characters in a string. Escapes double quote '"' in
125
325
  * addition to '&', '<', and '>' so that a string can be included in an HTML
126
326
  * tag attribute value within double quotes.
327
+ * Will emit known safe HTML as-is.
328
+ *
329
+ * @param {*} value The string-like value to be escaped. May not be a string,
330
+ * but the value will be coerced to a string.
331
+ * @return {string} An escaped version of value.
332
+ */
333
+ soy.$$escapeHtml = function(value) {
334
+ if (typeof value === 'object' && value &&
335
+ value.contentKind === soydata.SanitizedContentKind.HTML) {
336
+ return value.content;
337
+ }
338
+ return soy.esc.$$escapeHtmlHelper(value);
339
+ };
340
+
341
+
342
+ /**
343
+ * Escapes HTML special characters in a string so that it can be embedded in
344
+ * RCDATA.
345
+ * <p>
346
+ * Escapes HTML special characters so that the value will not prematurely end
347
+ * the body of a tag like {@code <textarea>} or {@code <title>}. RCDATA tags
348
+ * cannot contain other HTML entities, so it is not strictly necessary to escape
349
+ * HTML special characters except when part of that text looks like an HTML
350
+ * entity or like a close tag : {@code </textarea>}.
351
+ * <p>
352
+ * Will normalize known safe HTML to make sure that sanitized HTML (which could
353
+ * contain an innocuous {@code </textarea>} don't prematurely end an RCDATA
354
+ * element.
355
+ *
356
+ * @param {*} value The string-like value to be escaped. May not be a string,
357
+ * but the value will be coerced to a string.
358
+ * @return {string} An escaped version of value.
359
+ */
360
+ soy.$$escapeHtmlRcdata = function(value) {
361
+ if (typeof value === 'object' && value &&
362
+ value.contentKind === soydata.SanitizedContentKind.HTML) {
363
+ return soy.esc.$$normalizeHtmlHelper(value.content);
364
+ }
365
+ return soy.esc.$$escapeHtmlHelper(value);
366
+ };
367
+
368
+
369
+ /**
370
+ * Removes HTML tags from a string of known safe HTML so it can be used as an
371
+ * attribute value.
372
+ *
373
+ * @param {*} value The HTML to be escaped. May not be a string, but the
374
+ * value will be coerced to a string.
375
+ * @return {string} A representation of value without tags, HTML comments, or
376
+ * other content.
377
+ */
378
+ soy.$$stripHtmlTags = function(value) {
379
+ return String(value).replace(soy.esc.$$HTML_TAG_REGEX_, '');
380
+ };
381
+
382
+
383
+ /**
384
+ * Escapes HTML special characters in an HTML attribute value.
127
385
  *
128
- * @param {*} str The string to be escaped. Can be other types, but the value
386
+ * @param {*} value The HTML to be escaped. May not be a string, but the
387
+ * value will be coerced to a string.
388
+ * @return {string} An escaped version of value.
389
+ */
390
+ soy.$$escapeHtmlAttribute = function(value) {
391
+ if (typeof value === 'object' && value &&
392
+ value.contentKind === soydata.SanitizedContentKind.HTML) {
393
+ return soy.esc.$$normalizeHtmlHelper(soy.$$stripHtmlTags(value.content));
394
+ }
395
+ return soy.esc.$$escapeHtmlHelper(value);
396
+ };
397
+
398
+
399
+ /**
400
+ * Escapes HTML special characters in a string including space and other
401
+ * characters that can end an unquoted HTML attribute value.
402
+ *
403
+ * @param {*} value The HTML to be escaped. May not be a string, but the
404
+ * value will be coerced to a string.
405
+ * @return {string} An escaped version of value.
406
+ */
407
+ soy.$$escapeHtmlAttributeNospace = function(value) {
408
+ if (typeof value === 'object' && value &&
409
+ value.contentKind === soydata.SanitizedContentKind.HTML) {
410
+ return soy.esc.$$normalizeHtmlNospaceHelper(
411
+ soy.$$stripHtmlTags(value.content));
412
+ }
413
+ return soy.esc.$$escapeHtmlNospaceHelper(value);
414
+ };
415
+
416
+
417
+ /**
418
+ * Filters out strings that cannot be a substring of a valid HTML attribute.
419
+ *
420
+ * @param {*} value The value to escape. May not be a string, but the value
421
+ * will be coerced to a string.
422
+ * @return {string} A valid HTML attribute name part or name/value pair.
423
+ * {@code "zSoyz"} if the input is invalid.
424
+ */
425
+ soy.$$filterHtmlAttribute = function(value) {
426
+ if (typeof value === 'object' && value &&
427
+ value.contentKind === soydata.SanitizedContentKind.HTML_ATTRIBUTE) {
428
+ return value.content.replace(/=([^"']*)$/, '="$1"');
429
+ }
430
+ return soy.esc.$$filterHtmlAttributeHelper(value);
431
+ };
432
+
433
+
434
+ /**
435
+ * Filters out strings that cannot be a substring of a valid HTML element name.
436
+ *
437
+ * @param {*} value The value to escape. May not be a string, but the value
438
+ * will be coerced to a string.
439
+ * @return {string} A valid HTML element name part.
440
+ * {@code "zSoyz"} if the input is invalid.
441
+ */
442
+ soy.$$filterHtmlElementName = function(value) {
443
+ return soy.esc.$$filterHtmlElementNameHelper(value);
444
+ };
445
+
446
+
447
+ /**
448
+ * Escapes characters in the value to make it valid content for a JS string
449
+ * literal.
450
+ *
451
+ * @param {*} value The value to escape. May not be a string, but the value
129
452
  * will be coerced to a string.
130
- * @return {string} An escaped copy of the string.
131
- */
132
- soy.$$escapeHtml = function(str) {
133
- return goog.string.htmlEscape(String(str));
453
+ * @return {string} An escaped version of value.
454
+ * @deprecated
455
+ */
456
+ soy.$$escapeJs = function(value) {
457
+ return soy.$$escapeJsString(value);
134
458
  };
135
459
 
136
460
 
137
461
  /**
138
- * Escapes characters in the string to make it a valid content for a JS string literal.
462
+ * Escapes characters in the value to make it valid content for a JS string
463
+ * literal.
139
464
  *
140
- * @param {*} s The string to be escaped. Can be other types, but the value
465
+ * @param {*} value The value to escape. May not be a string, but the value
141
466
  * will be coerced to a string.
142
- * @return {string} An escaped copy of the string.
143
- */
144
- soy.$$escapeJs = function(s) {
145
- s = String(s);
146
- var sb = [];
147
- for (var i = 0; i < s.length; i++) {
148
- sb[i] = goog.string.escapeChar(s.charAt(i));
467
+ * @return {string} An escaped version of value.
468
+ */
469
+ soy.$$escapeJsString = function(value) {
470
+ if (typeof value === 'object' &&
471
+ value.contentKind === soydata.SanitizedContentKind.JS_STR_CHARS) {
472
+ return value.content;
473
+ }
474
+ return soy.esc.$$escapeJsStringHelper(value);
475
+ };
476
+
477
+
478
+ /**
479
+ * Encodes a value as a JavaScript literal.
480
+ *
481
+ * @param {*} value The value to escape. May not be a string, but the value
482
+ * will be coerced to a string.
483
+ * @return {string} A JavaScript code representation of the input.
484
+ */
485
+ soy.$$escapeJsValue = function(value) {
486
+ // We surround values with spaces so that they can't be interpolated into
487
+ // identifiers by accident.
488
+ // We could use parentheses but those might be interpreted as a function call.
489
+ if (value == null) { // Intentionally matches undefined.
490
+ // Java returns null from maps where there is no corresponding key while
491
+ // JS returns undefined.
492
+ // We always output null for compatibility with Java which does not have a
493
+ // distinct undefined value.
494
+ return ' null ';
495
+ }
496
+ switch (typeof value) {
497
+ case 'boolean': case 'number':
498
+ return ' ' + value + ' ';
499
+ default:
500
+ return "'" + soy.esc.$$escapeJsStringHelper(String(value)) + "'";
149
501
  }
150
- return sb.join('');
151
502
  };
152
503
 
153
504
 
154
505
  /**
155
- * Escapes a string so that it can be safely included in a URI
506
+ * Escapes characters in the string to make it valid content for a JS regular
507
+ * expression literal.
156
508
  *
157
- * @param {*} str The string to be escaped. Can be other types, but the value
509
+ * @param {*} value The value to escape. May not be a string, but the value
158
510
  * will be coerced to a string.
159
- * @return {string} An escaped copy of the string.
160
- */
161
- soy.$$escapeUri = function(str) {
162
- return goog.string.urlEncode(String(str));
511
+ * @return {string} An escaped version of value.
512
+ */
513
+ soy.$$escapeJsRegex = function(value) {
514
+ return soy.esc.$$escapeJsRegexHelper(value);
515
+ };
516
+
517
+
518
+ /**
519
+ * Matches all URI mark characters that conflict with HTML attribute delimiters
520
+ * or that cannot appear in a CSS uri.
521
+ * From <a href="http://www.w3.org/TR/CSS2/grammar.html">G.2: CSS grammar</a>
522
+ * <pre>
523
+ * url ([!#$%&*-~]|{nonascii}|{escape})*
524
+ * </pre>
525
+ *
526
+ * @type {RegExp}
527
+ * @private
528
+ */
529
+ soy.$$problematicUriMarks_ = /['()]/g;
530
+
531
+ /**
532
+ * @param {string} ch A single character in {@link soy.$$problematicUriMarks_}.
533
+ * @return {string}
534
+ * @private
535
+ */
536
+ soy.$$pctEncode_ = function(ch) {
537
+ return '%' + ch.charCodeAt(0).toString(16);
538
+ };
539
+
540
+ /**
541
+ * Escapes a string so that it can be safely included in a URI.
542
+ *
543
+ * @param {*} value The value to escape. May not be a string, but the value
544
+ * will be coerced to a string.
545
+ * @return {string} An escaped version of value.
546
+ */
547
+ soy.$$escapeUri = function(value) {
548
+ if (typeof value === 'object' &&
549
+ value.contentKind === soydata.SanitizedContentKind.URI) {
550
+ return soy.$$normalizeUri(value);
551
+ }
552
+ // Apostophes and parentheses are not matched by encodeURIComponent.
553
+ // They are technically special in URIs, but only appear in the obsolete mark
554
+ // production in Appendix D.2 of RFC 3986, so can be encoded without changing
555
+ // semantics.
556
+ var encoded = soy.esc.$$escapeUriHelper(value);
557
+ soy.$$problematicUriMarks_.lastIndex = 0;
558
+ if (soy.$$problematicUriMarks_.test(encoded)) {
559
+ return encoded.replace(soy.$$problematicUriMarks_, soy.$$pctEncode_);
560
+ }
561
+ return encoded;
562
+ };
563
+
564
+
565
+ /**
566
+ * Removes rough edges from a URI by escaping any raw HTML/JS string delimiters.
567
+ *
568
+ * @param {*} value The value to escape. May not be a string, but the value
569
+ * will be coerced to a string.
570
+ * @return {string} An escaped version of value.
571
+ */
572
+ soy.$$normalizeUri = function(value) {
573
+ return soy.esc.$$normalizeUriHelper(value);
574
+ };
575
+
576
+
577
+ /**
578
+ * Vets a URI's protocol and removes rough edges from a URI by escaping
579
+ * any raw HTML/JS string delimiters.
580
+ *
581
+ * @param {*} value The value to escape. May not be a string, but the value
582
+ * will be coerced to a string.
583
+ * @return {string} An escaped version of value.
584
+ */
585
+ soy.$$filterNormalizeUri = function(value) {
586
+ return soy.esc.$$filterNormalizeUriHelper(value);
587
+ };
588
+
589
+
590
+ /**
591
+ * Escapes a string so it can safely be included inside a quoted CSS string.
592
+ *
593
+ * @param {*} value The value to escape. May not be a string, but the value
594
+ * will be coerced to a string.
595
+ * @return {string} An escaped version of value.
596
+ */
597
+ soy.$$escapeCssString = function(value) {
598
+ return soy.esc.$$escapeCssStringHelper(value);
599
+ };
600
+
601
+
602
+ /**
603
+ * Encodes a value as a CSS identifier part, keyword, or quantity.
604
+ *
605
+ * @param {*} value The value to escape. May not be a string, but the value
606
+ * will be coerced to a string.
607
+ * @return {string} A safe CSS identifier part, keyword, or quanitity.
608
+ */
609
+ soy.$$filterCssValue = function(value) {
610
+ // Uses == to intentionally match null and undefined for Java compatibility.
611
+ if (value == null) {
612
+ return '';
613
+ }
614
+ return soy.esc.$$filterCssValueHelper(value);
615
+ };
616
+
617
+
618
+ // -----------------------------------------------------------------------------
619
+ // Basic directives/functions.
620
+
621
+
622
+ /**
623
+ * Converts \r\n, \r, and \n to <br>s
624
+ * @param {*} str The string in which to convert newlines.
625
+ * @return {string} A copy of {@code str} with converted newlines.
626
+ */
627
+ soy.$$changeNewlineToBr = function(str) {
628
+ return goog.string.newLineToBr(String(str), false);
163
629
  };
164
630
 
165
631
 
@@ -181,19 +647,80 @@ soy.$$insertWordBreaks = function(str, maxCharsBetweenWordBreaks) {
181
647
 
182
648
 
183
649
  /**
184
- * Converts \r\n, \r, and \n to <br>s
185
- * @param {*} str The string in which to convert newlines.
186
- * @return {string} A copy of {@code str} with converted newlines.
650
+ * Truncates a string to a given max length (if it's currently longer),
651
+ * optionally adding ellipsis at the end.
652
+ *
653
+ * @param {*} str The string to truncate. Can be other types, but the value will
654
+ * be coerced to a string.
655
+ * @param {number} maxLen The maximum length of the string after truncation
656
+ * (including ellipsis, if applicable).
657
+ * @param {boolean} doAddEllipsis Whether to add ellipsis if the string needs
658
+ * truncation.
659
+ * @return {string} The string after truncation.
187
660
  */
188
- soy.$$changeNewlineToBr = function(str) {
189
- return goog.string.newLineToBr(String(str), false);
661
+ soy.$$truncate = function(str, maxLen, doAddEllipsis) {
662
+
663
+ str = String(str);
664
+ if (str.length <= maxLen) {
665
+ return str; // no need to truncate
666
+ }
667
+
668
+ // If doAddEllipsis, either reduce maxLen to compensate, or else if maxLen is
669
+ // too small, just turn off doAddEllipsis.
670
+ if (doAddEllipsis) {
671
+ if (maxLen > 3) {
672
+ maxLen -= 3;
673
+ } else {
674
+ doAddEllipsis = false;
675
+ }
676
+ }
677
+
678
+ // Make sure truncating at maxLen doesn't cut up a unicode surrogate pair.
679
+ if (soy.$$isHighSurrogate_(str.charAt(maxLen - 1)) &&
680
+ soy.$$isLowSurrogate_(str.charAt(maxLen))) {
681
+ maxLen -= 1;
682
+ }
683
+
684
+ // Truncate.
685
+ str = str.substring(0, maxLen);
686
+
687
+ // Add ellipsis.
688
+ if (doAddEllipsis) {
689
+ str += '...';
690
+ }
691
+
692
+ return str;
693
+ };
694
+
695
+ /**
696
+ * Private helper for $$truncate() to check whether a char is a high surrogate.
697
+ * @param {string} ch The char to check.
698
+ * @return {boolean} Whether the given char is a unicode high surrogate.
699
+ * @private
700
+ */
701
+ soy.$$isHighSurrogate_ = function(ch) {
702
+ return 0xD800 <= ch && ch <= 0xDBFF;
190
703
  };
191
704
 
705
+ /**
706
+ * Private helper for $$truncate() to check whether a char is a low surrogate.
707
+ * @param {string} ch The char to check.
708
+ * @return {boolean} Whether the given char is a unicode low surrogate.
709
+ * @private
710
+ */
711
+ soy.$$isLowSurrogate_ = function(ch) {
712
+ return 0xDC00 <= ch && ch <= 0xDFFF;
713
+ };
714
+
715
+
716
+ // -----------------------------------------------------------------------------
717
+ // Bidi directives/functions.
718
+
192
719
 
193
720
  /**
194
721
  * Cache of bidi formatter by context directionality, so we don't keep on
195
722
  * creating new objects.
196
- * @type {Object}
723
+ * @type {!Object.<!goog.i18n.BidiFormatter>}
197
724
  * @private
198
725
  */
199
726
  soy.$$bidiFormatterCache_ = {};
@@ -206,13 +733,37 @@ soy.$$bidiFormatterCache_ = {};
206
733
  * @return {goog.i18n.BidiFormatter} A formatter for bidiGlobalDir.
207
734
  * @private
208
735
  */
209
- soy.$$bidiFormatterInstance_ = function(bidiGlobalDir) {
736
+ soy.$$getBidiFormatterInstance_ = function(bidiGlobalDir) {
210
737
  return soy.$$bidiFormatterCache_[bidiGlobalDir] ||
211
738
  (soy.$$bidiFormatterCache_[bidiGlobalDir] =
212
739
  new goog.i18n.BidiFormatter(bidiGlobalDir));
213
740
  };
214
741
 
215
742
 
743
+ /**
744
+ * Returns the leading horizontal edge, i.e. "left" or "right", depending on
745
+ * bidiGlobalDir.
746
+ * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
747
+ * if rtl, 0 if unknown.
748
+ * @return {string} "right" for RTL context and "left" otherwise.
749
+ */
750
+ soy.$$bidiStartEdge = function(bidiGlobalDir) {
751
+ return soy.$$getBidiFormatterInstance_(bidiGlobalDir).startEdge();
752
+ };
753
+
754
+
755
+ /**
756
+ * Returns the trailing horizontal edge, i.e. "right" or "left", depending on
757
+ * bidiGlobalDir.
758
+ * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
759
+ * if rtl, 0 if unknown.
760
+ * @return {string} "left" for RTL context and "right" otherwise.
761
+ */
762
+ soy.$$bidiEndEdge = function(bidiGlobalDir) {
763
+ return soy.$$getBidiFormatterInstance_(bidiGlobalDir).endEdge();
764
+ };
765
+
766
+
216
767
  /**
217
768
  * Estimate the overall directionality of text. If opt_isHtml, makes sure to
218
769
  * ignore the LTR nature of the mark-up and escapes in text, making the logic
@@ -241,12 +792,26 @@ soy.$$bidiTextDir = function(text, opt_isHtml) {
241
792
  * @param {string} text The text whose directionality is to be estimated.
242
793
  * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped.
243
794
  * Default: false.
244
- * @return {string} "dir=rtl" for RTL text in non-RTL context; "dir=ltr" for LTR
245
- * text in non-LTR context; else, the empty string.
795
+ * @return {soydata.SanitizedHtmlAttribute} "dir=rtl" for RTL text in non-RTL
796
+ * context; "dir=ltr" for LTR text in non-LTR context;
797
+ * else, the empty string.
246
798
  */
247
799
  soy.$$bidiDirAttr = function(bidiGlobalDir, text, opt_isHtml) {
248
- var formatter = soy.$$bidiFormatterInstance_(bidiGlobalDir);
249
- return formatter.dirAttr(text, opt_isHtml);
800
+ return new soydata.SanitizedHtmlAttribute(
801
+ soy.$$getBidiFormatterInstance_(bidiGlobalDir).dirAttr(text, opt_isHtml));
802
+ };
803
+
804
+
805
+ /**
806
+ * Returns a Unicode BiDi mark matching bidiGlobalDir (LRM or RLM), or an empty
807
+ * string if bidiGlobalDir is 0 (unknown).
808
+ * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
809
+ * if rtl, 0 if unknown.
810
+ * @return {string} A Unicode bidi mark matching bidiGlobalDir, or the empty
811
+ * string when bidiGlobalDir is 0 (unknown).
812
+ */
813
+ soy.$$bidiMark = function(bidiGlobalDir) {
814
+ return soy.$$getBidiFormatterInstance_(bidiGlobalDir).mark();
250
815
  };
251
816
 
252
817
 
@@ -261,12 +826,12 @@ soy.$$bidiDirAttr = function(bidiGlobalDir, text, opt_isHtml) {
261
826
  * @param {string} text The text whose directionality is to be estimated.
262
827
  * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped.
263
828
  * Default: false.
264
- * @return {string} A Unicode bidi mark matching bidiGlobalDir, or
265
- * the empty string when text's overall and exit directionalities both match
266
- * bidiGlobalDir.
829
+ * @return {string} A Unicode bidi mark matching bidiGlobalDir, or the empty
830
+ * string when text's overall and exit directionalities both match
831
+ * bidiGlobalDir, or bidiGlobalDir is 0 (unknown).
267
832
  */
268
833
  soy.$$bidiMarkAfter = function(bidiGlobalDir, text, opt_isHtml) {
269
- var formatter = soy.$$bidiFormatterInstance_(bidiGlobalDir);
834
+ var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir);
270
835
  return formatter.markAfter(text, opt_isHtml);
271
836
  };
272
837
 
@@ -284,7 +849,7 @@ soy.$$bidiMarkAfter = function(bidiGlobalDir, text, opt_isHtml) {
284
849
  * @return {string} The wrapped string.
285
850
  */
286
851
  soy.$$bidiSpanWrap = function(bidiGlobalDir, str) {
287
- var formatter = soy.$$bidiFormatterInstance_(bidiGlobalDir);
852
+ var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir);
288
853
  return formatter.spanWrap(str + '', true);
289
854
  };
290
855
 
@@ -303,6 +868,488 @@ soy.$$bidiSpanWrap = function(bidiGlobalDir, str) {
303
868
  * @return {string} The wrapped string.
304
869
  */
305
870
  soy.$$bidiUnicodeWrap = function(bidiGlobalDir, str) {
306
- var formatter = soy.$$bidiFormatterInstance_(bidiGlobalDir);
871
+ var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir);
307
872
  return formatter.unicodeWrap(str + '', true);
308
873
  };
874
+
875
+
876
+ // -----------------------------------------------------------------------------
877
+ // Generated code.
878
+
879
+
880
+
881
+
882
+ // START GENERATED CODE FOR ESCAPERS.
883
+
884
+ /**
885
+ * @type {function (*) : string}
886
+ */
887
+ soy.esc.$$escapeUriHelper = function(v) {
888
+ return goog.string.urlEncode(String(v));
889
+ };
890
+
891
+ /**
892
+ * Maps charcters to the escaped versions for the named escape directives.
893
+ * @type {Object.<string, string>}
894
+ * @private
895
+ */
896
+ soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = {
897
+ '\x00': '\x26#0;',
898
+ '\x22': '\x26quot;',
899
+ '\x26': '\x26amp;',
900
+ '\x27': '\x26#39;',
901
+ '\x3c': '\x26lt;',
902
+ '\x3e': '\x26gt;',
903
+ '\x09': '\x26#9;',
904
+ '\x0a': '\x26#10;',
905
+ '\x0b': '\x26#11;',
906
+ '\x0c': '\x26#12;',
907
+ '\x0d': '\x26#13;',
908
+ ' ': '\x26#32;',
909
+ '-': '\x26#45;',
910
+ '\/': '\x26#47;',
911
+ '\x3d': '\x26#61;',
912
+ '`': '\x26#96;',
913
+ '\x85': '\x26#133;',
914
+ '\xa0': '\x26#160;',
915
+ '\u2028': '\x26#8232;',
916
+ '\u2029': '\x26#8233;'
917
+ };
918
+
919
+ /**
920
+ * A function that can be used with String.replace..
921
+ * @param {string} ch A single character matched by a compatible matcher.
922
+ * @return {string} A token in the output language.
923
+ * @private
924
+ */
925
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = function(ch) {
926
+ return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_[ch];
927
+ };
928
+
929
+ /**
930
+ * Maps charcters to the escaped versions for the named escape directives.
931
+ * @type {Object.<string, string>}
932
+ * @private
933
+ */
934
+ soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = {
935
+ '\x00': '\\x00',
936
+ '\x08': '\\x08',
937
+ '\x09': '\\t',
938
+ '\x0a': '\\n',
939
+ '\x0b': '\\x0b',
940
+ '\x0c': '\\f',
941
+ '\x0d': '\\r',
942
+ '\x22': '\\x22',
943
+ '\x26': '\\x26',
944
+ '\x27': '\\x27',
945
+ '\/': '\\\/',
946
+ '\x3c': '\\x3c',
947
+ '\x3d': '\\x3d',
948
+ '\x3e': '\\x3e',
949
+ '\\': '\\\\',
950
+ '\x85': '\\x85',
951
+ '\u2028': '\\u2028',
952
+ '\u2029': '\\u2029',
953
+ '$': '\\x24',
954
+ '(': '\\x28',
955
+ ')': '\\x29',
956
+ '*': '\\x2a',
957
+ '+': '\\x2b',
958
+ ',': '\\x2c',
959
+ '-': '\\x2d',
960
+ '.': '\\x2e',
961
+ ':': '\\x3a',
962
+ '?': '\\x3f',
963
+ '[': '\\x5b',
964
+ ']': '\\x5d',
965
+ '^': '\\x5e',
966
+ '{': '\\x7b',
967
+ '|': '\\x7c',
968
+ '}': '\\x7d'
969
+ };
970
+
971
+ /**
972
+ * A function that can be used with String.replace..
973
+ * @param {string} ch A single character matched by a compatible matcher.
974
+ * @return {string} A token in the output language.
975
+ * @private
976
+ */
977
+ soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = function(ch) {
978
+ return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_[ch];
979
+ };
980
+
981
+ /**
982
+ * Maps charcters to the escaped versions for the named escape directives.
983
+ * @type {Object.<string, string>}
984
+ * @private
985
+ */
986
+ soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_ = {
987
+ '\x00': '\\0 ',
988
+ '\x08': '\\8 ',
989
+ '\x09': '\\9 ',
990
+ '\x0a': '\\a ',
991
+ '\x0b': '\\b ',
992
+ '\x0c': '\\c ',
993
+ '\x0d': '\\d ',
994
+ '\x22': '\\22 ',
995
+ '\x26': '\\26 ',
996
+ '\x27': '\\27 ',
997
+ '(': '\\28 ',
998
+ ')': '\\29 ',
999
+ '*': '\\2a ',
1000
+ '\/': '\\2f ',
1001
+ ':': '\\3a ',
1002
+ ';': '\\3b ',
1003
+ '\x3c': '\\3c ',
1004
+ '\x3d': '\\3d ',
1005
+ '\x3e': '\\3e ',
1006
+ '@': '\\40 ',
1007
+ '\\': '\\5c ',
1008
+ '{': '\\7b ',
1009
+ '}': '\\7d ',
1010
+ '\x85': '\\85 ',
1011
+ '\xa0': '\\a0 ',
1012
+ '\u2028': '\\2028 ',
1013
+ '\u2029': '\\2029 '
1014
+ };
1015
+
1016
+ /**
1017
+ * A function that can be used with String.replace..
1018
+ * @param {string} ch A single character matched by a compatible matcher.
1019
+ * @return {string} A token in the output language.
1020
+ * @private
1021
+ */
1022
+ soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_ = function(ch) {
1023
+ return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_[ch];
1024
+ };
1025
+
1026
+ /**
1027
+ * Maps charcters to the escaped versions for the named escape directives.
1028
+ * @type {Object.<string, string>}
1029
+ * @private
1030
+ */
1031
+ soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = {
1032
+ '\x00': '%00',
1033
+ '\x01': '%01',
1034
+ '\x02': '%02',
1035
+ '\x03': '%03',
1036
+ '\x04': '%04',
1037
+ '\x05': '%05',
1038
+ '\x06': '%06',
1039
+ '\x07': '%07',
1040
+ '\x08': '%08',
1041
+ '\x09': '%09',
1042
+ '\x0a': '%0A',
1043
+ '\x0b': '%0B',
1044
+ '\x0c': '%0C',
1045
+ '\x0d': '%0D',
1046
+ '\x0e': '%0E',
1047
+ '\x0f': '%0F',
1048
+ '\x10': '%10',
1049
+ '\x11': '%11',
1050
+ '\x12': '%12',
1051
+ '\x13': '%13',
1052
+ '\x14': '%14',
1053
+ '\x15': '%15',
1054
+ '\x16': '%16',
1055
+ '\x17': '%17',
1056
+ '\x18': '%18',
1057
+ '\x19': '%19',
1058
+ '\x1a': '%1A',
1059
+ '\x1b': '%1B',
1060
+ '\x1c': '%1C',
1061
+ '\x1d': '%1D',
1062
+ '\x1e': '%1E',
1063
+ '\x1f': '%1F',
1064
+ ' ': '%20',
1065
+ '\x22': '%22',
1066
+ '\x27': '%27',
1067
+ '(': '%28',
1068
+ ')': '%29',
1069
+ '\x3c': '%3C',
1070
+ '\x3e': '%3E',
1071
+ '\\': '%5C',
1072
+ '{': '%7B',
1073
+ '}': '%7D',
1074
+ '\x7f': '%7F',
1075
+ '\x85': '%C2%85',
1076
+ '\xa0': '%C2%A0',
1077
+ '\u2028': '%E2%80%A8',
1078
+ '\u2029': '%E2%80%A9',
1079
+ '\uff01': '%EF%BC%81',
1080
+ '\uff03': '%EF%BC%83',
1081
+ '\uff04': '%EF%BC%84',
1082
+ '\uff06': '%EF%BC%86',
1083
+ '\uff07': '%EF%BC%87',
1084
+ '\uff08': '%EF%BC%88',
1085
+ '\uff09': '%EF%BC%89',
1086
+ '\uff0a': '%EF%BC%8A',
1087
+ '\uff0b': '%EF%BC%8B',
1088
+ '\uff0c': '%EF%BC%8C',
1089
+ '\uff0f': '%EF%BC%8F',
1090
+ '\uff1a': '%EF%BC%9A',
1091
+ '\uff1b': '%EF%BC%9B',
1092
+ '\uff1d': '%EF%BC%9D',
1093
+ '\uff1f': '%EF%BC%9F',
1094
+ '\uff20': '%EF%BC%A0',
1095
+ '\uff3b': '%EF%BC%BB',
1096
+ '\uff3d': '%EF%BC%BD'
1097
+ };
1098
+
1099
+ /**
1100
+ * A function that can be used with String.replace..
1101
+ * @param {string} ch A single character matched by a compatible matcher.
1102
+ * @return {string} A token in the output language.
1103
+ * @private
1104
+ */
1105
+ soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = function(ch) {
1106
+ return soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_[ch];
1107
+ };
1108
+
1109
+ /**
1110
+ * Matches characters that need to be escaped for the named directives.
1111
+ * @type RegExp
1112
+ * @private
1113
+ */
1114
+ soy.esc.$$MATCHER_FOR_ESCAPE_HTML_ = /[\x00\x22\x26\x27\x3c\x3e]/g;
1115
+
1116
+ /**
1117
+ * Matches characters that need to be escaped for the named directives.
1118
+ * @type RegExp
1119
+ * @private
1120
+ */
1121
+ soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_ = /[\x00\x22\x27\x3c\x3e]/g;
1122
+
1123
+ /**
1124
+ * Matches characters that need to be escaped for the named directives.
1125
+ * @type RegExp
1126
+ * @private
1127
+ */
1128
+ soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x26\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g;
1129
+
1130
+ /**
1131
+ * Matches characters that need to be escaped for the named directives.
1132
+ * @type RegExp
1133
+ * @private
1134
+ */
1135
+ soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g;
1136
+
1137
+ /**
1138
+ * Matches characters that need to be escaped for the named directives.
1139
+ * @type RegExp
1140
+ * @private
1141
+ */
1142
+ soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_ = /[\x00\x08-\x0d\x22\x26\x27\/\x3c-\x3e\\\x85\u2028\u2029]/g;
1143
+
1144
+ /**
1145
+ * Matches characters that need to be escaped for the named directives.
1146
+ * @type RegExp
1147
+ * @private
1148
+ */
1149
+ soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_ = /[\x00\x08-\x0d\x22\x24\x26-\/\x3a\x3c-\x3f\x5b-\x5e\x7b-\x7d\x85\u2028\u2029]/g;
1150
+
1151
+ /**
1152
+ * Matches characters that need to be escaped for the named directives.
1153
+ * @type RegExp
1154
+ * @private
1155
+ */
1156
+ soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_ = /[\x00\x08-\x0d\x22\x26-\x2a\/\x3a-\x3e@\\\x7b\x7d\x85\xa0\u2028\u2029]/g;
1157
+
1158
+ /**
1159
+ * Matches characters that need to be escaped for the named directives.
1160
+ * @type RegExp
1161
+ * @private
1162
+ */
1163
+ soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = /[\x00- \x22\x27-\x29\x3c\x3e\\\x7b\x7d\x7f\x85\xa0\u2028\u2029\uff01\uff03\uff04\uff06-\uff0c\uff0f\uff1a\uff1b\uff1d\uff1f\uff20\uff3b\uff3d]/g;
1164
+
1165
+ /**
1166
+ * A pattern that vets values produced by the named directives.
1167
+ * @type RegExp
1168
+ * @private
1169
+ */
1170
+ soy.esc.$$FILTER_FOR_FILTER_CSS_VALUE_ = /^(?!-*(?:expression|(?:moz-)?binding))(?:[.#]?-?(?:[_a-z0-9-]+)(?:-[_a-z0-9-]+)*-?|-?(?:[0-9]+(?:\.[0-9]*)?|\.[0-9]+)(?:[a-z]{1,2}|%)?|!important|)$/i;
1171
+
1172
+ /**
1173
+ * A pattern that vets values produced by the named directives.
1174
+ * @type RegExp
1175
+ * @private
1176
+ */
1177
+ soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_ = /^(?:(?:https?|mailto):|[^&:\/?#]*(?:[\/?#]|$))/i;
1178
+
1179
+ /**
1180
+ * A pattern that vets values produced by the named directives.
1181
+ * @type RegExp
1182
+ * @private
1183
+ */
1184
+ soy.esc.$$FILTER_FOR_FILTER_HTML_ATTRIBUTE_ = /^(?!style|on|action|archive|background|cite|classid|codebase|data|dsync|href|longdesc|src|usemap)(?:[a-z0-9_$:-]*)$/i;
1185
+
1186
+ /**
1187
+ * A pattern that vets values produced by the named directives.
1188
+ * @type RegExp
1189
+ * @private
1190
+ */
1191
+ soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_ = /^(?!script|style|title|textarea|xmp|no)[a-z0-9_$:-]*$/i;
1192
+
1193
+ /**
1194
+ * A helper for the Soy directive |escapeHtml
1195
+ * @param {*} value Can be of any type but will be coerced to a string.
1196
+ * @return {string} The escaped text.
1197
+ */
1198
+ soy.esc.$$escapeHtmlHelper = function(value) {
1199
+ var str = String(value);
1200
+ return str.replace(
1201
+ soy.esc.$$MATCHER_FOR_ESCAPE_HTML_,
1202
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
1203
+ };
1204
+
1205
+ /**
1206
+ * A helper for the Soy directive |normalizeHtml
1207
+ * @param {*} value Can be of any type but will be coerced to a string.
1208
+ * @return {string} The escaped text.
1209
+ */
1210
+ soy.esc.$$normalizeHtmlHelper = function(value) {
1211
+ var str = String(value);
1212
+ return str.replace(
1213
+ soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_,
1214
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
1215
+ };
1216
+
1217
+ /**
1218
+ * A helper for the Soy directive |escapeHtmlNospace
1219
+ * @param {*} value Can be of any type but will be coerced to a string.
1220
+ * @return {string} The escaped text.
1221
+ */
1222
+ soy.esc.$$escapeHtmlNospaceHelper = function(value) {
1223
+ var str = String(value);
1224
+ return str.replace(
1225
+ soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_,
1226
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
1227
+ };
1228
+
1229
+ /**
1230
+ * A helper for the Soy directive |normalizeHtmlNospace
1231
+ * @param {*} value Can be of any type but will be coerced to a string.
1232
+ * @return {string} The escaped text.
1233
+ */
1234
+ soy.esc.$$normalizeHtmlNospaceHelper = function(value) {
1235
+ var str = String(value);
1236
+ return str.replace(
1237
+ soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_,
1238
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
1239
+ };
1240
+
1241
+ /**
1242
+ * A helper for the Soy directive |escapeJsString
1243
+ * @param {*} value Can be of any type but will be coerced to a string.
1244
+ * @return {string} The escaped text.
1245
+ */
1246
+ soy.esc.$$escapeJsStringHelper = function(value) {
1247
+ var str = String(value);
1248
+ return str.replace(
1249
+ soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_,
1250
+ soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_);
1251
+ };
1252
+
1253
+ /**
1254
+ * A helper for the Soy directive |escapeJsRegex
1255
+ * @param {*} value Can be of any type but will be coerced to a string.
1256
+ * @return {string} The escaped text.
1257
+ */
1258
+ soy.esc.$$escapeJsRegexHelper = function(value) {
1259
+ var str = String(value);
1260
+ return str.replace(
1261
+ soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_,
1262
+ soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_);
1263
+ };
1264
+
1265
+ /**
1266
+ * A helper for the Soy directive |escapeCssString
1267
+ * @param {*} value Can be of any type but will be coerced to a string.
1268
+ * @return {string} The escaped text.
1269
+ */
1270
+ soy.esc.$$escapeCssStringHelper = function(value) {
1271
+ var str = String(value);
1272
+ return str.replace(
1273
+ soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_,
1274
+ soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_);
1275
+ };
1276
+
1277
+ /**
1278
+ * A helper for the Soy directive |filterCssValue
1279
+ * @param {*} value Can be of any type but will be coerced to a string.
1280
+ * @return {string} The escaped text.
1281
+ */
1282
+ soy.esc.$$filterCssValueHelper = function(value) {
1283
+ var str = String(value);
1284
+ if (!soy.esc.$$FILTER_FOR_FILTER_CSS_VALUE_.test(str)) {
1285
+ goog.asserts.fail('Bad value `%s` for |filterCssValue', [str]);
1286
+ return 'zSoyz';
1287
+ }
1288
+ return str;
1289
+ };
1290
+
1291
+ /**
1292
+ * A helper for the Soy directive |normalizeUri
1293
+ * @param {*} value Can be of any type but will be coerced to a string.
1294
+ * @return {string} The escaped text.
1295
+ */
1296
+ soy.esc.$$normalizeUriHelper = function(value) {
1297
+ var str = String(value);
1298
+ return str.replace(
1299
+ soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_,
1300
+ soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_);
1301
+ };
1302
+
1303
+ /**
1304
+ * A helper for the Soy directive |filterNormalizeUri
1305
+ * @param {*} value Can be of any type but will be coerced to a string.
1306
+ * @return {string} The escaped text.
1307
+ */
1308
+ soy.esc.$$filterNormalizeUriHelper = function(value) {
1309
+ var str = String(value);
1310
+ if (!soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_.test(str)) {
1311
+ goog.asserts.fail('Bad value `%s` for |filterNormalizeUri', [str]);
1312
+ return 'zSoyz';
1313
+ }
1314
+ return str.replace(
1315
+ soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_,
1316
+ soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_);
1317
+ };
1318
+
1319
+ /**
1320
+ * A helper for the Soy directive |filterHtmlAttribute
1321
+ * @param {*} value Can be of any type but will be coerced to a string.
1322
+ * @return {string} The escaped text.
1323
+ */
1324
+ soy.esc.$$filterHtmlAttributeHelper = function(value) {
1325
+ var str = String(value);
1326
+ if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ATTRIBUTE_.test(str)) {
1327
+ goog.asserts.fail('Bad value `%s` for |filterHtmlAttribute', [str]);
1328
+ return 'zSoyz';
1329
+ }
1330
+ return str;
1331
+ };
1332
+
1333
+ /**
1334
+ * A helper for the Soy directive |filterHtmlElementName
1335
+ * @param {*} value Can be of any type but will be coerced to a string.
1336
+ * @return {string} The escaped text.
1337
+ */
1338
+ soy.esc.$$filterHtmlElementNameHelper = function(value) {
1339
+ var str = String(value);
1340
+ if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_.test(str)) {
1341
+ goog.asserts.fail('Bad value `%s` for |filterHtmlElementName', [str]);
1342
+ return 'zSoyz';
1343
+ }
1344
+ return str;
1345
+ };
1346
+
1347
+ /**
1348
+ * Matches all tags, HTML comments, and DOCTYPEs in tag soup HTML.
1349
+ *
1350
+ * @type {RegExp}
1351
+ * @private
1352
+ */
1353
+ soy.esc.$$HTML_TAG_REGEX_ = /<(?:!|\/?[a-zA-Z])(?:[^>'"]|"[^"]*"|'[^']*')*>/g;
1354
+
1355
+ // END GENERATED CODE