yellow-brick-road 0.2.2 → 0.2.3

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 (34) hide show
  1. data/README.rst +9 -1
  2. data/Rakefile +0 -3
  3. data/lib/generators/templates/yellow_brick_road.rb.erb +12 -0
  4. data/lib/tasks/ybr.rake +12 -0
  5. data/lib/yellow-brick-road.rb +5 -0
  6. data/lib/yellow-brick-road/config.rb +45 -6
  7. data/lib/yellow-brick-road/directive_processor.rb +89 -10
  8. data/lib/yellow-brick-road/engine.rb +10 -0
  9. data/lib/yellow-brick-road/protobuf_js.rb +32 -0
  10. data/lib/yellow-brick-road/soy_processor.rb +13 -4
  11. data/lib/yellow-brick-road/utils.rb +7 -1
  12. data/lib/yellow-brick-road/version.rb +1 -1
  13. data/test/dummy/app/assets/javascripts/application.js +1 -0
  14. data/test/dummy/app/assets/javascripts/closure-deps.js +2 -1
  15. data/test/dummy/app/assets/javascripts/protos/person.pb.js +207 -0
  16. data/test/dummy/app/protos/person.proto +5 -0
  17. data/test/dummy/log/development.log +1544 -0
  18. data/test/dummy/tmp/cache/assets/C5B/240/sprockets%2Fc561864da49634b1e8464990f63f4123 +314 -0
  19. data/test/dummy/tmp/cache/assets/C7E/9F0/sprockets%2F89862076204c62c4593ac20de32da909 +6 -5
  20. data/test/dummy/tmp/cache/assets/CBD/850/sprockets%2F9191c7b83dca8e9342628ac59e452229 +297 -0
  21. data/test/dummy/tmp/cache/assets/CCC/BB0/sprockets%2F649c7cc1e706997576646e6dd790d7a0 +0 -0
  22. data/test/dummy/tmp/cache/assets/CE0/AB0/sprockets%2Fb8f01070d8f72dd30306684ef61858ac +204 -0
  23. data/test/dummy/tmp/cache/assets/CF7/BC0/sprockets%2Fe47129798756fd8f35bd4350bff5e461 +213 -0
  24. data/test/dummy/tmp/cache/assets/D15/F60/sprockets%2Fa28394e3f80365b5bc86794dd46daa22 +0 -0
  25. data/test/dummy/tmp/cache/assets/D50/F20/sprockets%2Fd858e852254b667a8efffa4f12d96d11 +0 -0
  26. data/test/dummy/tmp/cache/assets/D6B/0C0/sprockets%2F8c3bdd9c000f7f5a26e91f294a71c3c4 +0 -0
  27. data/test/dummy/tmp/cache/assets/D6F/6D0/sprockets%2Ff9f65ec20235e6595b5eb2ab91f15bb4 +1441 -0
  28. data/test/dummy/tmp/cache/assets/D84/210/sprockets%2Fabd0103ccec2b428ac62c94e4c40b384 +7 -5
  29. data/test/dummy/tmp/cache/assets/D97/E60/sprockets%2F18762119fe3a03903efaac2bfceec628 +763 -0
  30. data/test/dummy/tmp/cache/assets/DA1/670/sprockets%2Fccb4ba5dcd2f7696c636666ca5ab6057 +60 -0
  31. data/test/dummy/tmp/cache/assets/DED/040/sprockets%2Fd3aa2ab8d25cde3b6fb324dbb8c42933 +746 -0
  32. data/test/dummy/tmp/cache/assets/E04/890/sprockets%2F2f5173deea6c795b8fdde723bb4b63af +0 -0
  33. metadata +38 -11
  34. data/lib/tasks/yellow-brick-road_tasks.rake +0 -4
@@ -0,0 +1,204 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1326427868.259806: @value{ I" length:EFi I" digest;
2
+ F"%cfbd63de7608404dc258aebb498707b8I" source;
3
+ FI" // Copyright 2008 The Closure Library Authors. All Rights Reserved.
4
+ //
5
+ // Licensed under the Apache License, Version 2.0 (the "License");
6
+ // you may not use this file except in compliance with the License.
7
+ // You may obtain a copy of the License at
8
+ //
9
+ // http://www.apache.org/licenses/LICENSE-2.0
10
+ //
11
+ // Unless required by applicable law or agreed to in writing, software
12
+ // distributed under the License is distributed on an "AS-IS" BASIS,
13
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ // See the License for the specific language governing permissions and
15
+ // limitations under the License.
16
+
17
+ /**
18
+ * @fileoverview Protocol Buffer (Message) Descriptor class.
19
+ */
20
+
21
+
22
+ goog.provide('goog.proto2.Descriptor');
23
+ goog.provide('goog.proto2.Metadata');
24
+
25
+ goog.require('goog.array');
26
+ goog.require('goog.object');
27
+ goog.require('goog.proto2.Util');
28
+
29
+
30
+ /**
31
+ * @typedef {{name: (string|undefined),
32
+ * fullName: (string|undefined),
33
+ * containingType: (goog.proto2.Message|undefined)}}
34
+ */
35
+ goog.proto2.Metadata;
36
+
37
+
38
+
39
+ /**
40
+ * A class which describes a Protocol Buffer 2 Message.
41
+ *
42
+ * @param {Function} messageType Constructor for the message class that
43
+ * this descriptor describes.
44
+ * @param {!goog.proto2.Metadata} metadata The metadata about the message that
45
+ * will be used to construct this descriptor.
46
+ * @param {Array.<!goog.proto2.FieldDescriptor>} fields The fields of the
47
+ * message described by this descriptor.
48
+ *
49
+ * @constructor
50
+ */
51
+ goog.proto2.Descriptor = function(messageType, metadata, fields) {
52
+
53
+ /**
54
+ * @type {Function}
55
+ * @private
56
+ */
57
+ this.messageType_ = messageType;
58
+
59
+ /**
60
+ * @type {?string}
61
+ * @private
62
+ */
63
+ this.name_ = metadata.name || null;
64
+
65
+ /**
66
+ * @type {?string}
67
+ * @private
68
+ */
69
+ this.fullName_ = metadata.fullName || null;
70
+
71
+ /**
72
+ * @type {goog.proto2.Message|undefined}
73
+ * @private
74
+ */
75
+ this.containingType_ = metadata.containingType;
76
+
77
+ /**
78
+ * The fields of the message described by this descriptor.
79
+ * @type {!Object.<number, !goog.proto2.FieldDescriptor>}
80
+ * @private
81
+ */
82
+ this.fields_ = {};
83
+
84
+ for (var i = 0; i < fields.length; i++) {
85
+ var field = fields[i];
86
+ this.fields_[field.getTag()] = field;
87
+ }
88
+ };
89
+
90
+
91
+ /**
92
+ * Returns the name of the message, if any.
93
+ *
94
+ * @return {?string} The name.
95
+ */
96
+ goog.proto2.Descriptor.prototype.getName = function() {
97
+ return this.name_;
98
+ };
99
+
100
+
101
+ /**
102
+ * Returns the full name of the message, if any.
103
+ *
104
+ * @return {?string} The name.
105
+ */
106
+ goog.proto2.Descriptor.prototype.getFullName = function() {
107
+ return this.fullName_;
108
+ };
109
+
110
+
111
+ /**
112
+ * Returns the descriptor of the containing message type or null if none.
113
+ *
114
+ * @return {goog.proto2.Descriptor} The descriptor.
115
+ */
116
+ goog.proto2.Descriptor.prototype.getContainingType = function() {
117
+ if (!this.containingType_) {
118
+ return null;
119
+ }
120
+
121
+ return this.containingType_.getDescriptor();
122
+ };
123
+
124
+
125
+ /**
126
+ * Returns the fields in the message described by this descriptor ordered by
127
+ * tag.
128
+ *
129
+ * @return {!Array.<!goog.proto2.FieldDescriptor>} The array of field
130
+ * descriptors.
131
+ */
132
+ goog.proto2.Descriptor.prototype.getFields = function() {
133
+ /**
134
+ * @param {!goog.proto2.FieldDescriptor} fieldA First field.
135
+ * @param {!goog.proto2.FieldDescriptor} fieldB Second field.
136
+ * @return {number} Negative if fieldA's tag number is smaller, positive
137
+ * if greater, zero if the same.
138
+ */
139
+ function tagComparator(fieldA, fieldB) {
140
+ return fieldA.getTag() - fieldB.getTag();
141
+ };
142
+
143
+ var fields = goog.object.getValues(this.fields_);
144
+ goog.array.sort(fields, tagComparator);
145
+
146
+ return fields;
147
+ };
148
+
149
+
150
+ /**
151
+ * Returns the fields in the message as a key/value map, where the key is
152
+ * the tag number of the field.
153
+ *
154
+ * @return {!Object.<number, !goog.proto2.FieldDescriptor>} The field map.
155
+ */
156
+ goog.proto2.Descriptor.prototype.getFieldsMap = function() {
157
+ return goog.object.clone(this.fields_);
158
+ };
159
+
160
+
161
+ /**
162
+ * Returns the field matching the given name, if any. Note that
163
+ * this method searches over the *original* name of the field,
164
+ * not the camelCase version.
165
+ *
166
+ * @param {string} name The field name for which to search.
167
+ *
168
+ * @return {goog.proto2.FieldDescriptor} The field found, if any.
169
+ */
170
+ goog.proto2.Descriptor.prototype.findFieldByName = function(name) {
171
+ var valueFound = goog.object.findValue(this.fields_,
172
+ function(field, key, obj) {
173
+ return field.getName() == name;
174
+ });
175
+
176
+ return /** @type {goog.proto2.FieldDescriptor} */ (valueFound) || null;
177
+ };
178
+
179
+
180
+ /**
181
+ * Returns the field matching the given tag number, if any.
182
+ *
183
+ * @param {number|string} tag The field tag number for which to search.
184
+ *
185
+ * @return {goog.proto2.FieldDescriptor} The field found, if any.
186
+ */
187
+ goog.proto2.Descriptor.prototype.findFieldByTag = function(tag) {
188
+ goog.proto2.Util.assert(goog.string.isNumeric(tag));
189
+ return this.fields_[parseInt(tag, 10)] || null;
190
+ };
191
+
192
+
193
+ /**
194
+ * Creates an instance of the message type that this descriptor
195
+ * describes.
196
+ *
197
+ * @return {goog.proto2.Message} The instance of the message.
198
+ */
199
+ goog.proto2.Descriptor.prototype.createMessageInstance = function() {
200
+ return new this.messageType_;
201
+ };
202
+ ;
203
+ FI"
204
+ F"%389879fce7849e189a03ac0e3ce30e3c
@@ -0,0 +1,213 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1326427868.3619132: @value{ I" length:EFiI" digest;
2
+ F"%e094d15a885dca1a845038ecac9df1e7I" source;
3
+ FI"// Generated by the protocol buffer compiler. DO NOT EDIT!
4
+ // source: person.proto
5
+
6
+ /**
7
+ * @fileoverview Generated Protocol Buffer code for file person.proto.
8
+ */
9
+
10
+
11
+ goog.provide('Person');
12
+
13
+ goog.require('goog.proto2.Message');
14
+
15
+
16
+
17
+ /**
18
+ * Message Person.
19
+ * @constructor
20
+ * @extends {goog.proto2.Message}
21
+ */
22
+ Person = function() {
23
+ goog.proto2.Message.apply(this);
24
+ };
25
+ goog.inherits(Person, goog.proto2.Message);
26
+
27
+
28
+ /**
29
+ * Overrides {@link goog.proto2.Message#clone} to specify its exact return type.
30
+ * @return {!Person} The cloned message.
31
+ * @override
32
+ */
33
+ Person.prototype.clone;
34
+
35
+
36
+ /**
37
+ * Gets the value of the id field.
38
+ * @return {?number} The value.
39
+ */
40
+ Person.prototype.getId = function() {
41
+ return /** @type {?number} */ (this.get$Value(1));
42
+ };
43
+
44
+
45
+ /**
46
+ * Gets the value of the id field or the default value if not set.
47
+ * @return {number} The value.
48
+ */
49
+ Person.prototype.getIdOrDefault = function() {
50
+ return /** @type {number} */ (this.get$ValueOrDefault(1));
51
+ };
52
+
53
+
54
+ /**
55
+ * Sets the value of the id field.
56
+ * @param {number} value The value.
57
+ */
58
+ Person.prototype.setId = function(value) {
59
+ this.set$Value(1, value);
60
+ };
61
+
62
+
63
+ /**
64
+ * @return {boolean} Whether the id field has a value.
65
+ */
66
+ Person.prototype.hasId = function() {
67
+ return this.has$Value(1);
68
+ };
69
+
70
+
71
+ /**
72
+ * @return {number} The number of values in the id field.
73
+ */
74
+ Person.prototype.idCount = function() {
75
+ return this.count$Values(1);
76
+ };
77
+
78
+
79
+ /**
80
+ * Clears the values in the id field.
81
+ */
82
+ Person.prototype.clearId = function() {
83
+ this.clear$Field(1);
84
+ };
85
+
86
+
87
+ /**
88
+ * Gets the value of the name field.
89
+ * @return {?string} The value.
90
+ */
91
+ Person.prototype.getName = function() {
92
+ return /** @type {?string} */ (this.get$Value(2));
93
+ };
94
+
95
+
96
+ /**
97
+ * Gets the value of the name field or the default value if not set.
98
+ * @return {string} The value.
99
+ */
100
+ Person.prototype.getNameOrDefault = function() {
101
+ return /** @type {string} */ (this.get$ValueOrDefault(2));
102
+ };
103
+
104
+
105
+ /**
106
+ * Sets the value of the name field.
107
+ * @param {string} value The value.
108
+ */
109
+ Person.prototype.setName = function(value) {
110
+ this.set$Value(2, value);
111
+ };
112
+
113
+
114
+ /**
115
+ * @return {boolean} Whether the name field has a value.
116
+ */
117
+ Person.prototype.hasName = function() {
118
+ return this.has$Value(2);
119
+ };
120
+
121
+
122
+ /**
123
+ * @return {number} The number of values in the name field.
124
+ */
125
+ Person.prototype.nameCount = function() {
126
+ return this.count$Values(2);
127
+ };
128
+
129
+
130
+ /**
131
+ * Clears the values in the name field.
132
+ */
133
+ Person.prototype.clearName = function() {
134
+ this.clear$Field(2);
135
+ };
136
+
137
+
138
+ /**
139
+ * Gets the value of the email field.
140
+ * @return {?string} The value.
141
+ */
142
+ Person.prototype.getEmail = function() {
143
+ return /** @type {?string} */ (this.get$Value(3));
144
+ };
145
+
146
+
147
+ /**
148
+ * Gets the value of the email field or the default value if not set.
149
+ * @return {string} The value.
150
+ */
151
+ Person.prototype.getEmailOrDefault = function() {
152
+ return /** @type {string} */ (this.get$ValueOrDefault(3));
153
+ };
154
+
155
+
156
+ /**
157
+ * Sets the value of the email field.
158
+ * @param {string} value The value.
159
+ */
160
+ Person.prototype.setEmail = function(value) {
161
+ this.set$Value(3, value);
162
+ };
163
+
164
+
165
+ /**
166
+ * @return {boolean} Whether the email field has a value.
167
+ */
168
+ Person.prototype.hasEmail = function() {
169
+ return this.has$Value(3);
170
+ };
171
+
172
+
173
+ /**
174
+ * @return {number} The number of values in the email field.
175
+ */
176
+ Person.prototype.emailCount = function() {
177
+ return this.count$Values(3);
178
+ };
179
+
180
+
181
+ /**
182
+ * Clears the values in the email field.
183
+ */
184
+ Person.prototype.clearEmail = function() {
185
+ this.clear$Field(3);
186
+ };
187
+
188
+
189
+
190
+ goog.proto2.Message.set$Metadata(Person, {
191
+ 0: {
192
+ name: 'Person',
193
+ fullName: 'Person'
194
+ },
195
+ 1: {
196
+ name: 'id',
197
+ fieldType: goog.proto2.Message.FieldType.INT32,
198
+ type: Number
199
+ },
200
+ 2: {
201
+ name: 'name',
202
+ fieldType: goog.proto2.Message.FieldType.STRING,
203
+ type: String
204
+ },
205
+ 3: {
206
+ name: 'email',
207
+ fieldType: goog.proto2.Message.FieldType.STRING,
208
+ type: String
209
+ }
210
+ });
211
+ ;
212
+ FI"
213
+ F"%f2adef3c66a0be991e16bcbbc687b5e5
@@ -0,0 +1,1441 @@
1
+ o: ActiveSupport::Cache::Entry :@compressedF:@expires_in0:@created_atf1326429404.936157: @value{I"
2
+ class:EFI"BundledAsset;
3
+ FI"id;
4
+ F"%4c4a1aea600811f886dc11fe14d5d532I"logical_path;
5
+ FI"soyutils_usegoog.js;
6
+ TI"
7
+ F"l/Volumes/Development/dev-web/gems/yellow-brick-road/vendor/closure-soyutils-usegoog/soyutils_usegoog.jsI"content_type;
8
+ FI"application/javascript;
9
+ FI"
10
+ mtime;
11
+ FI"2011-12-22T12:03:48+00:00;
12
+ FI" body;
13
+ FI"�/*
14
+ * Copyright 2008 Google Inc.
15
+ *
16
+ * Licensed under the Apache License, Version 2.0 (the "License");
17
+ * you may not use this file except in compliance with the License.
18
+ * You may obtain a copy of the License at
19
+ *
20
+ * http://www.apache.org/licenses/LICENSE-2.0
21
+ *
22
+ * Unless required by applicable law or agreed to in writing, software
23
+ * distributed under the License is distributed on an "AS IS" BASIS,
24
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25
+ * See the License for the specific language governing permissions and
26
+ * limitations under the License.
27
+ */
28
+
29
+ /**
30
+ * @fileoverview
31
+ * Utility functions and classes for Soy.
32
+ *
33
+ * <p>
34
+ * The top portion of this file contains utilities for Soy users:<ul>
35
+ * <li> soy.StringBuilder: Compatible with the 'stringbuilder' code style.
36
+ * <li> soy.renderElement: Render template and set as innerHTML of an element.
37
+ * <li> soy.renderAsFragment: Render template and return as HTML fragment.
38
+ * </ul>
39
+ *
40
+ * <p>
41
+ * The bottom portion of this file contains utilities that should only be called
42
+ * by Soy-generated JS code. Please do not use these functions directly from
43
+ * your hand-writen code. Their names all start with '$$'.
44
+ *
45
+ */
46
+
47
+
48
+ goog.provide('soy');
49
+ goog.provide('soy.StringBuilder');
50
+ goog.provide('soy.esc');
51
+ goog.provide('soydata');
52
+ goog.provide('soydata.SanitizedHtml');
53
+ goog.provide('soydata.SanitizedHtmlAttribute');
54
+ goog.provide('soydata.SanitizedJsStrChars');
55
+ goog.provide('soydata.SanitizedUri');
56
+
57
+ goog.require('goog.asserts');
58
+ goog.require('goog.dom.DomHelper');
59
+ goog.require('goog.format');
60
+ goog.require('goog.i18n.BidiFormatter');
61
+ goog.require('goog.i18n.bidi');
62
+ goog.require('goog.soy');
63
+ goog.require('goog.string');
64
+ goog.require('goog.string.StringBuffer');
65
+
66
+
67
+ // -----------------------------------------------------------------------------
68
+ // StringBuilder (compatible with the 'stringbuilder' code style).
69
+
70
+
71
+ /**
72
+ * Utility class to facilitate much faster string concatenation in IE,
73
+ * using Array.join() rather than the '+' operator. For other browsers
74
+ * we simply use the '+' operator.
75
+ *
76
+ * @param {Object} var_args Initial items to append,
77
+ * e.g., new soy.StringBuilder('foo', 'bar').
78
+ * @constructor
79
+ */
80
+ soy.StringBuilder = goog.string.StringBuffer;
81
+
82
+
83
+ // -----------------------------------------------------------------------------
84
+ // soydata: Defines typed strings, e.g. an HTML string {@code "a<b>c"} is
85
+ // semantically distinct from the plain text string {@code "a<b>c"} and smart
86
+ // templates can take that distinction into account.
87
+
88
+ /**
89
+ * A type of textual content.
90
+ * @enum {number}
91
+ */
92
+ soydata.SanitizedContentKind = {
93
+
94
+ /**
95
+ * A snippet of HTML that does not start or end inside a tag, comment, entity,
96
+ * or DOCTYPE; and that does not contain any executable code
97
+ * (JS, {@code <object>}s, etc.) from a different trust domain.
98
+ */
99
+ HTML: 0,
100
+
101
+ /**
102
+ * A sequence of code units that can appear between quotes (either kind) in a
103
+ * JS program without causing a parse error, and without causing any side
104
+ * effects.
105
+ * <p>
106
+ * The content should not contain unescaped quotes, newlines, or anything else
107
+ * that would cause parsing to fail or to cause a JS parser to finish the
108
+ * string its parsing inside the content.
109
+ * <p>
110
+ * The content must also not end inside an escape sequence ; no partial octal
111
+ * escape sequences or odd number of '{@code \}'s at the end.
112
+ */
113
+ JS_STR_CHARS: 1,
114
+
115
+ /** A properly encoded portion of a URI. */
116
+ URI: 2,
117
+
118
+ /** An attribute name and value such as {@code dir="ltr"}. */
119
+ HTML_ATTRIBUTE: 3
120
+ };
121
+
122
+
123
+ /**
124
+ * A string-like object that carries a content-type.
125
+ * @param {string} content
126
+ * @constructor
127
+ * @private
128
+ */
129
+ soydata.SanitizedContent = function(content) {
130
+ /**
131
+ * The textual content.
132
+ * @type {string}
133
+ */
134
+ this.content = content;
135
+ };
136
+
137
+ /** @type {soydata.SanitizedContentKind} */
138
+ soydata.SanitizedContent.prototype.contentKind;
139
+
140
+ /** @override */
141
+ soydata.SanitizedContent.prototype.toString = function() {
142
+ return this.content;
143
+ };
144
+
145
+
146
+ /**
147
+ * Content of type {@link soydata.SanitizedContentKind.HTML}.
148
+ * @param {string} content A string of HTML that can safely be embedded in
149
+ * a PCDATA context in your app. If you would be surprised to find that an
150
+ * HTML sanitizer produced {@code s} (e.g. it runs code or fetches bad URLs)
151
+ * and you wouldn't write a template that produces {@code s} on security or
152
+ * privacy grounds, then don't pass {@code s} here.
153
+ * @constructor
154
+ * @extends {soydata.SanitizedContent}
155
+ */
156
+ soydata.SanitizedHtml = function(content) {
157
+ soydata.SanitizedContent.call(this, content);
158
+ };
159
+ goog.inherits(soydata.SanitizedHtml, soydata.SanitizedContent);
160
+
161
+ /** @override */
162
+ soydata.SanitizedHtml.prototype.contentKind = soydata.SanitizedContentKind.HTML;
163
+
164
+
165
+ /**
166
+ * Content of type {@link soydata.SanitizedContentKind.JS_STR_CHARS}.
167
+ * @param {string} content A string of JS that when evaled, produces a
168
+ * value that does not depend on any sensitive data and has no side effects
169
+ * <b>OR</b> a string of JS that does not reference any variables or have
170
+ * any side effects not known statically to the app authors.
171
+ * @constructor
172
+ * @extends {soydata.SanitizedContent}
173
+ */
174
+ soydata.SanitizedJsStrChars = function(content) {
175
+ soydata.SanitizedContent.call(this, content);
176
+ };
177
+ goog.inherits(soydata.SanitizedJsStrChars, soydata.SanitizedContent);
178
+
179
+ /** @override */
180
+ soydata.SanitizedJsStrChars.prototype.contentKind =
181
+ soydata.SanitizedContentKind.JS_STR_CHARS;
182
+
183
+
184
+ /**
185
+ * Content of type {@link soydata.SanitizedContentKind.URI}.
186
+ * @param {string} content A chunk of URI that the caller knows is safe to
187
+ * emit in a template.
188
+ * @constructor
189
+ * @extends {soydata.SanitizedContent}
190
+ */
191
+ soydata.SanitizedUri = function(content) {
192
+ soydata.SanitizedContent.call(this, content);
193
+ };
194
+ goog.inherits(soydata.SanitizedUri, soydata.SanitizedContent);
195
+
196
+ /** @override */
197
+ soydata.SanitizedUri.prototype.contentKind = soydata.SanitizedContentKind.URI;
198
+
199
+
200
+ /**
201
+ * Content of type {@link soydata.SanitizedContentKind.HTML_ATTRIBUTE}.
202
+ * @param {string} content An attribute name and value, such as
203
+ * {@code dir="ltr"}.
204
+ * @constructor
205
+ * @extends {soydata.SanitizedContent}
206
+ */
207
+ soydata.SanitizedHtmlAttribute = function(content) {
208
+ soydata.SanitizedContent.call(this, content);
209
+ };
210
+ goog.inherits(soydata.SanitizedHtmlAttribute, soydata.SanitizedContent);
211
+
212
+ /** @override */
213
+ soydata.SanitizedHtmlAttribute.prototype.contentKind =
214
+ soydata.SanitizedContentKind.HTML_ATTRIBUTE;
215
+
216
+
217
+ // -----------------------------------------------------------------------------
218
+ // Public utilities.
219
+
220
+
221
+ /**
222
+ * Helper function to render a Soy template and then set the output string as
223
+ * the innerHTML of an element. It is recommended to use this helper function
224
+ * instead of directly setting innerHTML in your hand-written code, so that it
225
+ * will be easier to audit the code for cross-site scripting vulnerabilities.
226
+ *
227
+ * NOTE: New code should consider using goog.soy.renderElement instead.
228
+ *
229
+ * @param {Element} element The element whose content we are rendering.
230
+ * @param {Function} template The Soy template defining the element's content.
231
+ * @param {Object=} opt_templateData The data for the template.
232
+ * @param {Object=} opt_injectedData The injected data for the template.
233
+ */
234
+ soy.renderElement = goog.soy.renderElement;
235
+
236
+
237
+ /**
238
+ * Helper function to render a Soy template into a single node or a document
239
+ * fragment. If the rendered HTML string represents a single node, then that
240
+ * node is returned (note that this is *not* a fragment, despite them name of
241
+ * the method). Otherwise a document fragment is returned containing the
242
+ * rendered nodes.
243
+ *
244
+ * NOTE: New code should consider using goog.soy.renderAsFragment
245
+ * instead (note that the arguments are different).
246
+ *
247
+ * @param {Function} template The Soy template defining the element's content.
248
+ * @param {Object=} opt_templateData The data for the template.
249
+ * @param {Document=} opt_document The document used to create DOM nodes. If not
250
+ * specified, global document object is used.
251
+ * @param {Object=} opt_injectedData The injected data for the template.
252
+ * @return {!Node} The resulting node or document fragment.
253
+ */
254
+ soy.renderAsFragment = function(
255
+ template, opt_templateData, opt_document, opt_injectedData) {
256
+ return goog.soy.renderAsFragment(
257
+ template, opt_templateData, opt_injectedData,
258
+ new goog.dom.DomHelper(opt_document));
259
+ };
260
+
261
+
262
+ /**
263
+ * Helper function to render a Soy template into a single node. If the rendered
264
+ * HTML string represents a single node, then that node is returned. Otherwise,
265
+ * a DIV element is returned containing the rendered nodes.
266
+ *
267
+ * NOTE: New code should consider using goog.soy.renderAsElement
268
+ * instead (note that the arguments are different).
269
+ *
270
+ * @param {Function} template The Soy template defining the element's content.
271
+ * @param {Object=} opt_templateData The data for the template.
272
+ * @param {Document=} opt_document The document used to create DOM nodes. If not
273
+ * specified, global document object is used.
274
+ * @param {Object=} opt_injectedData The injected data for the template.
275
+ * @return {!Element} Rendered template contents, wrapped in a parent DIV
276
+ * element if necessary.
277
+ */
278
+ soy.renderAsElement = function(
279
+ template, opt_templateData, opt_document, opt_injectedData) {
280
+ return goog.soy.renderAsElement(
281
+ template, opt_templateData, opt_injectedData,
282
+ new goog.dom.DomHelper(opt_document));
283
+ };
284
+
285
+
286
+ // -----------------------------------------------------------------------------
287
+ // Below are private utilities to be used by Soy-generated code only.
288
+
289
+
290
+ /**
291
+ * Builds an augmented data object to be passed when a template calls another,
292
+ * and needs to pass both original data and additional params. The returned
293
+ * object will contain both the original data and the additional params. If the
294
+ * same key appears in both, then the value from the additional params will be
295
+ * visible, while the value from the original data will be hidden. The original
296
+ * data object will be used, but not modified.
297
+ *
298
+ * @param {!Object} origData The original data to pass.
299
+ * @param {Object} additionalParams The additional params to pass.
300
+ * @return {Object} An augmented data object containing both the original data
301
+ * and the additional params.
302
+ */
303
+ soy.$$augmentData = function(origData, additionalParams) {
304
+
305
+ // Create a new object whose '__proto__' field is set to origData.
306
+ /** @constructor */
307
+ function TempCtor() {}
308
+ TempCtor.prototype = origData;
309
+ var newData = new TempCtor();
310
+
311
+ // Add the additional params to the new object.
312
+ for (var key in additionalParams) {
313
+ newData[key] = additionalParams[key];
314
+ }
315
+
316
+ return newData;
317
+ };
318
+
319
+
320
+ /**
321
+ * Gets the keys in a map as an array. There are no guarantees on the order.
322
+ * @param {Object} map The map to get the keys of.
323
+ * @return {Array.<string>} The array of keys in the given map.
324
+ */
325
+ soy.$$getMapKeys = function(map) {
326
+ var mapKeys = [];
327
+ for (var key in map) {
328
+ mapKeys.push(key);
329
+ }
330
+ return mapKeys;
331
+ };
332
+
333
+
334
+ /**
335
+ * Gets a consistent unique id for the given delegate template name. Two calls
336
+ * to this function will return the same id if and only if the input names are
337
+ * the same.
338
+ *
339
+ * <p> Important: This function must always be called with a string constant.
340
+ *
341
+ * <p> If Closure Compiler is not being used, then this is just this identity
342
+ * function. If Closure Compiler is being used, then each call to this function
343
+ * will be replaced with a short string constant, which will be consistent per
344
+ * input name.
345
+ *
346
+ * @param {string} delTemplateName The delegate template name for which to get a
347
+ * consistent unique id.
348
+ * @return {string} A unique id that is consistent per input name.
349
+ *
350
+ * @consistentIdGenerator
351
+ */
352
+ soy.$$getDelegateId = function(delTemplateName) {
353
+ return delTemplateName;
354
+ };
355
+
356
+
357
+ /**
358
+ * Map from registered delegate template id/name to the priority of the
359
+ * implementation.
360
+ * @type {Object}
361
+ * @private
362
+ */
363
+ soy.$$DELEGATE_REGISTRY_PRIORITIES_ = {};
364
+
365
+ /**
366
+ * Map from registered delegate template id/name to the implementation function.
367
+ * @type {Object}
368
+ * @private
369
+ */
370
+ soy.$$DELEGATE_REGISTRY_FUNCTIONS_ = {};
371
+
372
+
373
+ /**
374
+ * Registers a delegate implementation. If the same delegate template id/name
375
+ * has been registered previously, then priority values are compared and only
376
+ * the higher priority implementation is stored (if priorities are equal, an
377
+ * error is thrown).
378
+ *
379
+ * @param {string} delTemplateId The delegate template id/name to register.
380
+ * @param {number} delPriority The implementation's priority value.
381
+ * @param {Function} delFn The implementation function.
382
+ */
383
+ soy.$$registerDelegateFn = function(delTemplateId, delPriority, delFn) {
384
+ var mapKey = 'key_' + delTemplateId;
385
+ var currPriority = soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey];
386
+ if (currPriority === undefined || delPriority > currPriority) {
387
+ // Registering new or higher-priority function: replace registry entry.
388
+ soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey] = delPriority;
389
+ soy.$$DELEGATE_REGISTRY_FUNCTIONS_[mapKey] = delFn;
390
+ } else if (delPriority == currPriority) {
391
+ // Registering same-priority function: error.
392
+ throw Error(
393
+ 'Encountered two active delegates with same priority (id/name "' +
394
+ delTemplateId + '").');
395
+ } else {
396
+ // Registering lower-priority function: do nothing.
397
+ }
398
+ };
399
+
400
+
401
+ /**
402
+ * Retrieves the (highest-priority) implementation that has been registered for
403
+ * a given delegate template id/name. If no implementation has been registered
404
+ * for the id/name, then returns an implementation that is equivalent to an
405
+ * empty template (i.e. rendered output would be empty string).
406
+ *
407
+ * @param {string} delTemplateId The delegate template id/name to get.
408
+ * @return {Function} The retrieved implementation function.
409
+ */
410
+ soy.$$getDelegateFn = function(delTemplateId) {
411
+ var delFn = soy.$$DELEGATE_REGISTRY_FUNCTIONS_['key_' + delTemplateId];
412
+ return delFn ? delFn : soy.$$EMPTY_TEMPLATE_FN_;
413
+ };
414
+
415
+
416
+ /**
417
+ * Private helper soy.$$getDelegateFn(). This is the empty template function
418
+ * that is returned whenever there's no delegate implementation found.
419
+ *
420
+ * @param {Object.<string, *>=} opt_data
421
+ * @param {soy.StringBuilder=} opt_sb
422
+ * @param {Object.<string, *>=} opt_ijData
423
+ * @return {string}
424
+ * @private
425
+ */
426
+ soy.$$EMPTY_TEMPLATE_FN_ = function(opt_data, opt_sb, opt_ijData) {
427
+ return '';
428
+ };
429
+
430
+
431
+ // -----------------------------------------------------------------------------
432
+ // Escape/filter/normalize.
433
+
434
+
435
+ /**
436
+ * Escapes HTML special characters in a string. Escapes double quote '"' in
437
+ * addition to '&', '<', and '>' so that a string can be included in an HTML
438
+ * tag attribute value within double quotes.
439
+ * Will emit known safe HTML as-is.
440
+ *
441
+ * @param {*} value The string-like value to be escaped. May not be a string,
442
+ * but the value will be coerced to a string.
443
+ * @return {string} An escaped version of value.
444
+ */
445
+ soy.$$escapeHtml = function(value) {
446
+ if (typeof value === 'object' && value &&
447
+ value.contentKind === soydata.SanitizedContentKind.HTML) {
448
+ return value.content;
449
+ }
450
+ return soy.esc.$$escapeHtmlHelper(value);
451
+ };
452
+
453
+
454
+ /**
455
+ * Escapes HTML special characters in a string so that it can be embedded in
456
+ * RCDATA.
457
+ * <p>
458
+ * Escapes HTML special characters so that the value will not prematurely end
459
+ * the body of a tag like {@code <textarea>} or {@code <title>}. RCDATA tags
460
+ * cannot contain other HTML entities, so it is not strictly necessary to escape
461
+ * HTML special characters except when part of that text looks like an HTML
462
+ * entity or like a close tag : {@code </textarea>}.
463
+ * <p>
464
+ * Will normalize known safe HTML to make sure that sanitized HTML (which could
465
+ * contain an innocuous {@code </textarea>} don't prematurely end an RCDATA
466
+ * element.
467
+ *
468
+ * @param {*} value The string-like value to be escaped. May not be a string,
469
+ * but the value will be coerced to a string.
470
+ * @return {string} An escaped version of value.
471
+ */
472
+ soy.$$escapeHtmlRcdata = function(value) {
473
+ if (typeof value === 'object' && value &&
474
+ value.contentKind === soydata.SanitizedContentKind.HTML) {
475
+ return soy.esc.$$normalizeHtmlHelper(value.content);
476
+ }
477
+ return soy.esc.$$escapeHtmlHelper(value);
478
+ };
479
+
480
+
481
+ /**
482
+ * Removes HTML tags from a string of known safe HTML so it can be used as an
483
+ * attribute value.
484
+ *
485
+ * @param {*} value The HTML to be escaped. May not be a string, but the
486
+ * value will be coerced to a string.
487
+ * @return {string} A representation of value without tags, HTML comments, or
488
+ * other content.
489
+ */
490
+ soy.$$stripHtmlTags = function(value) {
491
+ return String(value).replace(soy.esc.$$HTML_TAG_REGEX_, '');
492
+ };
493
+
494
+
495
+ /**
496
+ * Escapes HTML special characters in an HTML attribute value.
497
+ *
498
+ * @param {*} value The HTML to be escaped. May not be a string, but the
499
+ * value will be coerced to a string.
500
+ * @return {string} An escaped version of value.
501
+ */
502
+ soy.$$escapeHtmlAttribute = function(value) {
503
+ if (typeof value === 'object' && value &&
504
+ value.contentKind === soydata.SanitizedContentKind.HTML) {
505
+ return soy.esc.$$normalizeHtmlHelper(soy.$$stripHtmlTags(value.content));
506
+ }
507
+ return soy.esc.$$escapeHtmlHelper(value);
508
+ };
509
+
510
+
511
+ /**
512
+ * Escapes HTML special characters in a string including space and other
513
+ * characters that can end an unquoted HTML attribute value.
514
+ *
515
+ * @param {*} value The HTML to be escaped. May not be a string, but the
516
+ * value will be coerced to a string.
517
+ * @return {string} An escaped version of value.
518
+ */
519
+ soy.$$escapeHtmlAttributeNospace = function(value) {
520
+ if (typeof value === 'object' && value &&
521
+ value.contentKind === soydata.SanitizedContentKind.HTML) {
522
+ return soy.esc.$$normalizeHtmlNospaceHelper(
523
+ soy.$$stripHtmlTags(value.content));
524
+ }
525
+ return soy.esc.$$escapeHtmlNospaceHelper(value);
526
+ };
527
+
528
+
529
+ /**
530
+ * Filters out strings that cannot be a substring of a valid HTML attribute.
531
+ *
532
+ * @param {*} value The value to escape. May not be a string, but the value
533
+ * will be coerced to a string.
534
+ * @return {string} A valid HTML attribute name part or name/value pair.
535
+ * {@code "zSoyz"} if the input is invalid.
536
+ */
537
+ soy.$$filterHtmlAttribute = function(value) {
538
+ if (typeof value === 'object' && value &&
539
+ value.contentKind === soydata.SanitizedContentKind.HTML_ATTRIBUTE) {
540
+ return value.content.replace(/=([^"']*)$/, '="$1"');
541
+ }
542
+ return soy.esc.$$filterHtmlAttributeHelper(value);
543
+ };
544
+
545
+
546
+ /**
547
+ * Filters out strings that cannot be a substring of a valid HTML element name.
548
+ *
549
+ * @param {*} value The value to escape. May not be a string, but the value
550
+ * will be coerced to a string.
551
+ * @return {string} A valid HTML element name part.
552
+ * {@code "zSoyz"} if the input is invalid.
553
+ */
554
+ soy.$$filterHtmlElementName = function(value) {
555
+ return soy.esc.$$filterHtmlElementNameHelper(value);
556
+ };
557
+
558
+
559
+ /**
560
+ * Escapes characters in the value to make it valid content for a JS string
561
+ * literal.
562
+ *
563
+ * @param {*} value The value to escape. May not be a string, but the value
564
+ * will be coerced to a string.
565
+ * @return {string} An escaped version of value.
566
+ * @deprecated
567
+ */
568
+ soy.$$escapeJs = function(value) {
569
+ return soy.$$escapeJsString(value);
570
+ };
571
+
572
+
573
+ /**
574
+ * Escapes characters in the value to make it valid content for a JS string
575
+ * literal.
576
+ *
577
+ * @param {*} value The value to escape. May not be a string, but the value
578
+ * will be coerced to a string.
579
+ * @return {string} An escaped version of value.
580
+ */
581
+ soy.$$escapeJsString = function(value) {
582
+ if (typeof value === 'object' &&
583
+ value.contentKind === soydata.SanitizedContentKind.JS_STR_CHARS) {
584
+ return value.content;
585
+ }
586
+ return soy.esc.$$escapeJsStringHelper(value);
587
+ };
588
+
589
+
590
+ /**
591
+ * Encodes a value as a JavaScript literal.
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} A JavaScript code representation of the input.
596
+ */
597
+ soy.$$escapeJsValue = function(value) {
598
+ // We surround values with spaces so that they can't be interpolated into
599
+ // identifiers by accident.
600
+ // We could use parentheses but those might be interpreted as a function call.
601
+ if (value == null) { // Intentionally matches undefined.
602
+ // Java returns null from maps where there is no corresponding key while
603
+ // JS returns undefined.
604
+ // We always output null for compatibility with Java which does not have a
605
+ // distinct undefined value.
606
+ return ' null ';
607
+ }
608
+ switch (typeof value) {
609
+ case 'boolean': case 'number':
610
+ return ' ' + value + ' ';
611
+ default:
612
+ return "'" + soy.esc.$$escapeJsStringHelper(String(value)) + "'";
613
+ }
614
+ };
615
+
616
+
617
+ /**
618
+ * Escapes characters in the string to make it valid content for a JS regular
619
+ * expression literal.
620
+ *
621
+ * @param {*} value The value to escape. May not be a string, but the value
622
+ * will be coerced to a string.
623
+ * @return {string} An escaped version of value.
624
+ */
625
+ soy.$$escapeJsRegex = function(value) {
626
+ return soy.esc.$$escapeJsRegexHelper(value);
627
+ };
628
+
629
+
630
+ /**
631
+ * Matches all URI mark characters that conflict with HTML attribute delimiters
632
+ * or that cannot appear in a CSS uri.
633
+ * From <a href="http://www.w3.org/TR/CSS2/grammar.html">G.2: CSS grammar</a>
634
+ * <pre>
635
+ * url ([!#$%&*-~]|{nonascii}|{escape})*
636
+ * </pre>
637
+ *
638
+ * @type {RegExp}
639
+ * @private
640
+ */
641
+ soy.$$problematicUriMarks_ = /['()]/g;
642
+
643
+ /**
644
+ * @param {string} ch A single character in {@link soy.$$problematicUriMarks_}.
645
+ * @return {string}
646
+ * @private
647
+ */
648
+ soy.$$pctEncode_ = function(ch) {
649
+ return '%' + ch.charCodeAt(0).toString(16);
650
+ };
651
+
652
+ /**
653
+ * Escapes a string so that it can be safely included in a URI.
654
+ *
655
+ * @param {*} value The value to escape. May not be a string, but the value
656
+ * will be coerced to a string.
657
+ * @return {string} An escaped version of value.
658
+ */
659
+ soy.$$escapeUri = function(value) {
660
+ if (typeof value === 'object' &&
661
+ value.contentKind === soydata.SanitizedContentKind.URI) {
662
+ return soy.$$normalizeUri(value);
663
+ }
664
+ // Apostophes and parentheses are not matched by encodeURIComponent.
665
+ // They are technically special in URIs, but only appear in the obsolete mark
666
+ // production in Appendix D.2 of RFC 3986, so can be encoded without changing
667
+ // semantics.
668
+ var encoded = soy.esc.$$escapeUriHelper(value);
669
+ soy.$$problematicUriMarks_.lastIndex = 0;
670
+ if (soy.$$problematicUriMarks_.test(encoded)) {
671
+ return encoded.replace(soy.$$problematicUriMarks_, soy.$$pctEncode_);
672
+ }
673
+ return encoded;
674
+ };
675
+
676
+
677
+ /**
678
+ * Removes rough edges from a URI by escaping any raw HTML/JS string delimiters.
679
+ *
680
+ * @param {*} value The value to escape. May not be a string, but the value
681
+ * will be coerced to a string.
682
+ * @return {string} An escaped version of value.
683
+ */
684
+ soy.$$normalizeUri = function(value) {
685
+ return soy.esc.$$normalizeUriHelper(value);
686
+ };
687
+
688
+
689
+ /**
690
+ * Vets a URI's protocol and removes rough edges from a URI by escaping
691
+ * any raw HTML/JS string delimiters.
692
+ *
693
+ * @param {*} value The value to escape. May not be a string, but the value
694
+ * will be coerced to a string.
695
+ * @return {string} An escaped version of value.
696
+ */
697
+ soy.$$filterNormalizeUri = function(value) {
698
+ return soy.esc.$$filterNormalizeUriHelper(value);
699
+ };
700
+
701
+
702
+ /**
703
+ * Escapes a string so it can safely be included inside a quoted CSS string.
704
+ *
705
+ * @param {*} value The value to escape. May not be a string, but the value
706
+ * will be coerced to a string.
707
+ * @return {string} An escaped version of value.
708
+ */
709
+ soy.$$escapeCssString = function(value) {
710
+ return soy.esc.$$escapeCssStringHelper(value);
711
+ };
712
+
713
+
714
+ /**
715
+ * Encodes a value as a CSS identifier part, keyword, or quantity.
716
+ *
717
+ * @param {*} value The value to escape. May not be a string, but the value
718
+ * will be coerced to a string.
719
+ * @return {string} A safe CSS identifier part, keyword, or quanitity.
720
+ */
721
+ soy.$$filterCssValue = function(value) {
722
+ // Uses == to intentionally match null and undefined for Java compatibility.
723
+ if (value == null) {
724
+ return '';
725
+ }
726
+ return soy.esc.$$filterCssValueHelper(value);
727
+ };
728
+
729
+
730
+ // -----------------------------------------------------------------------------
731
+ // Basic directives/functions.
732
+
733
+
734
+ /**
735
+ * Converts \r\n, \r, and \n to <br>s
736
+ * @param {*} str The string in which to convert newlines.
737
+ * @return {string} A copy of {@code str} with converted newlines.
738
+ */
739
+ soy.$$changeNewlineToBr = function(str) {
740
+ return goog.string.newLineToBr(String(str), false);
741
+ };
742
+
743
+
744
+ /**
745
+ * Inserts word breaks ('wbr' tags) into a HTML string at a given interval. The
746
+ * counter is reset if a space is encountered. Word breaks aren't inserted into
747
+ * HTML tags or entities. Entites count towards the character count; HTML tags
748
+ * do not.
749
+ *
750
+ * @param {*} str The HTML string to insert word breaks into. Can be other
751
+ * types, but the value will be coerced to a string.
752
+ * @param {number} maxCharsBetweenWordBreaks Maximum number of non-space
753
+ * characters to allow before adding a word break.
754
+ * @return {string} The string including word breaks.
755
+ */
756
+ soy.$$insertWordBreaks = function(str, maxCharsBetweenWordBreaks) {
757
+ return goog.format.insertWordBreaks(String(str), maxCharsBetweenWordBreaks);
758
+ };
759
+
760
+
761
+ /**
762
+ * Truncates a string to a given max length (if it's currently longer),
763
+ * optionally adding ellipsis at the end.
764
+ *
765
+ * @param {*} str The string to truncate. Can be other types, but the value will
766
+ * be coerced to a string.
767
+ * @param {number} maxLen The maximum length of the string after truncation
768
+ * (including ellipsis, if applicable).
769
+ * @param {boolean} doAddEllipsis Whether to add ellipsis if the string needs
770
+ * truncation.
771
+ * @return {string} The string after truncation.
772
+ */
773
+ soy.$$truncate = function(str, maxLen, doAddEllipsis) {
774
+
775
+ str = String(str);
776
+ if (str.length <= maxLen) {
777
+ return str; // no need to truncate
778
+ }
779
+
780
+ // If doAddEllipsis, either reduce maxLen to compensate, or else if maxLen is
781
+ // too small, just turn off doAddEllipsis.
782
+ if (doAddEllipsis) {
783
+ if (maxLen > 3) {
784
+ maxLen -= 3;
785
+ } else {
786
+ doAddEllipsis = false;
787
+ }
788
+ }
789
+
790
+ // Make sure truncating at maxLen doesn't cut up a unicode surrogate pair.
791
+ if (soy.$$isHighSurrogate_(str.charAt(maxLen - 1)) &&
792
+ soy.$$isLowSurrogate_(str.charAt(maxLen))) {
793
+ maxLen -= 1;
794
+ }
795
+
796
+ // Truncate.
797
+ str = str.substring(0, maxLen);
798
+
799
+ // Add ellipsis.
800
+ if (doAddEllipsis) {
801
+ str += '...';
802
+ }
803
+
804
+ return str;
805
+ };
806
+
807
+ /**
808
+ * Private helper for $$truncate() to check whether a char is a high surrogate.
809
+ * @param {string} ch The char to check.
810
+ * @return {boolean} Whether the given char is a unicode high surrogate.
811
+ * @private
812
+ */
813
+ soy.$$isHighSurrogate_ = function(ch) {
814
+ return 0xD800 <= ch && ch <= 0xDBFF;
815
+ };
816
+
817
+ /**
818
+ * Private helper for $$truncate() to check whether a char is a low surrogate.
819
+ * @param {string} ch The char to check.
820
+ * @return {boolean} Whether the given char is a unicode low surrogate.
821
+ * @private
822
+ */
823
+ soy.$$isLowSurrogate_ = function(ch) {
824
+ return 0xDC00 <= ch && ch <= 0xDFFF;
825
+ };
826
+
827
+
828
+ // -----------------------------------------------------------------------------
829
+ // Bidi directives/functions.
830
+
831
+
832
+ /**
833
+ * Cache of bidi formatter by context directionality, so we don't keep on
834
+ * creating new objects.
835
+ * @type {!Object.<!goog.i18n.BidiFormatter>}
836
+ * @private
837
+ */
838
+ soy.$$bidiFormatterCache_ = {};
839
+
840
+
841
+ /**
842
+ * Returns cached bidi formatter for bidiGlobalDir, or creates a new one.
843
+ * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
844
+ * if rtl, 0 if unknown.
845
+ * @return {goog.i18n.BidiFormatter} A formatter for bidiGlobalDir.
846
+ * @private
847
+ */
848
+ soy.$$getBidiFormatterInstance_ = function(bidiGlobalDir) {
849
+ return soy.$$bidiFormatterCache_[bidiGlobalDir] ||
850
+ (soy.$$bidiFormatterCache_[bidiGlobalDir] =
851
+ new goog.i18n.BidiFormatter(bidiGlobalDir));
852
+ };
853
+
854
+
855
+ /**
856
+ * Estimate the overall directionality of text. If opt_isHtml, makes sure to
857
+ * ignore the LTR nature of the mark-up and escapes in text, making the logic
858
+ * suitable for HTML and HTML-escaped text.
859
+ * @param {string} text The text whose directionality is to be estimated.
860
+ * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped.
861
+ * Default: false.
862
+ * @return {number} 1 if text is LTR, -1 if it is RTL, and 0 if it is neutral.
863
+ */
864
+ soy.$$bidiTextDir = function(text, opt_isHtml) {
865
+ if (!text) {
866
+ return 0;
867
+ }
868
+ return goog.i18n.bidi.detectRtlDirectionality(text, opt_isHtml) ? -1 : 1;
869
+ };
870
+
871
+
872
+ /**
873
+ * Returns "dir=ltr" or "dir=rtl", depending on text's estimated
874
+ * directionality, if it is not the same as bidiGlobalDir.
875
+ * Otherwise, returns the empty string.
876
+ * If opt_isHtml, makes sure to ignore the LTR nature of the mark-up and escapes
877
+ * in text, making the logic suitable for HTML and HTML-escaped text.
878
+ * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
879
+ * if rtl, 0 if unknown.
880
+ * @param {string} text The text whose directionality is to be estimated.
881
+ * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped.
882
+ * Default: false.
883
+ * @return {soydata.SanitizedHtmlAttribute} "dir=rtl" for RTL text in non-RTL
884
+ * context; "dir=ltr" for LTR text in non-LTR context;
885
+ * else, the empty string.
886
+ */
887
+ soy.$$bidiDirAttr = function(bidiGlobalDir, text, opt_isHtml) {
888
+ return new soydata.SanitizedHtmlAttribute(
889
+ soy.$$getBidiFormatterInstance_(bidiGlobalDir).dirAttr(text, opt_isHtml));
890
+ };
891
+
892
+
893
+ /**
894
+ * Returns a Unicode BiDi mark matching bidiGlobalDir (LRM or RLM) if the
895
+ * directionality or the exit directionality of text are opposite to
896
+ * bidiGlobalDir. Otherwise returns the empty string.
897
+ * If opt_isHtml, makes sure to ignore the LTR nature of the mark-up and escapes
898
+ * in text, making the logic suitable for HTML and HTML-escaped text.
899
+ * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
900
+ * if rtl, 0 if unknown.
901
+ * @param {string} text The text whose directionality is to be estimated.
902
+ * @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped.
903
+ * Default: false.
904
+ * @return {string} A Unicode bidi mark matching bidiGlobalDir, or the empty
905
+ * string when text's overall and exit directionalities both match
906
+ * bidiGlobalDir, or bidiGlobalDir is 0 (unknown).
907
+ */
908
+ soy.$$bidiMarkAfter = function(bidiGlobalDir, text, opt_isHtml) {
909
+ var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir);
910
+ return formatter.markAfter(text, opt_isHtml);
911
+ };
912
+
913
+
914
+ /**
915
+ * Returns str wrapped in a <span dir=ltr|rtl> according to its directionality -
916
+ * but only if that is neither neutral nor the same as the global context.
917
+ * Otherwise, returns str unchanged.
918
+ * Always treats str as HTML/HTML-escaped, i.e. ignores mark-up and escapes when
919
+ * estimating str's directionality.
920
+ * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
921
+ * if rtl, 0 if unknown.
922
+ * @param {*} str The string to be wrapped. Can be other types, but the value
923
+ * will be coerced to a string.
924
+ * @return {string} The wrapped string.
925
+ */
926
+ soy.$$bidiSpanWrap = function(bidiGlobalDir, str) {
927
+ var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir);
928
+ return formatter.spanWrap(str + '', true);
929
+ };
930
+
931
+
932
+ /**
933
+ * Returns str wrapped in Unicode BiDi formatting characters according to its
934
+ * directionality, i.e. either LRE or RLE at the beginning and PDF at the end -
935
+ * but only if str's directionality is neither neutral nor the same as the
936
+ * global context. Otherwise, returns str unchanged.
937
+ * Always treats str as HTML/HTML-escaped, i.e. ignores mark-up and escapes when
938
+ * estimating str's directionality.
939
+ * @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
940
+ * if rtl, 0 if unknown.
941
+ * @param {*} str The string to be wrapped. Can be other types, but the value
942
+ * will be coerced to a string.
943
+ * @return {string} The wrapped string.
944
+ */
945
+ soy.$$bidiUnicodeWrap = function(bidiGlobalDir, str) {
946
+ var formatter = soy.$$getBidiFormatterInstance_(bidiGlobalDir);
947
+ return formatter.unicodeWrap(str + '', true);
948
+ };
949
+
950
+
951
+ // -----------------------------------------------------------------------------
952
+ // Generated code.
953
+
954
+
955
+
956
+
957
+ // START GENERATED CODE FOR ESCAPERS.
958
+
959
+ /**
960
+ * @type {function (*) : string}
961
+ */
962
+ soy.esc.$$escapeUriHelper = function(v) {
963
+ return goog.string.urlEncode(String(v));
964
+ };
965
+
966
+ /**
967
+ * Maps charcters to the escaped versions for the named escape directives.
968
+ * @type {Object.<string, string>}
969
+ * @private
970
+ */
971
+ soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = {
972
+ '\x00': '\x26#0;',
973
+ '\x22': '\x26quot;',
974
+ '\x26': '\x26amp;',
975
+ '\x27': '\x26#39;',
976
+ '\x3c': '\x26lt;',
977
+ '\x3e': '\x26gt;',
978
+ '\x09': '\x26#9;',
979
+ '\x0a': '\x26#10;',
980
+ '\x0b': '\x26#11;',
981
+ '\x0c': '\x26#12;',
982
+ '\x0d': '\x26#13;',
983
+ ' ': '\x26#32;',
984
+ '-': '\x26#45;',
985
+ '\/': '\x26#47;',
986
+ '\x3d': '\x26#61;',
987
+ '`': '\x26#96;',
988
+ '\x85': '\x26#133;',
989
+ '\xa0': '\x26#160;',
990
+ '\u2028': '\x26#8232;',
991
+ '\u2029': '\x26#8233;'
992
+ };
993
+
994
+ /**
995
+ * A function that can be used with String.replace..
996
+ * @param {string} ch A single character matched by a compatible matcher.
997
+ * @return {string} A token in the output language.
998
+ * @private
999
+ */
1000
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = function(ch) {
1001
+ return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_[ch];
1002
+ };
1003
+
1004
+ /**
1005
+ * Maps charcters to the escaped versions for the named escape directives.
1006
+ * @type {Object.<string, string>}
1007
+ * @private
1008
+ */
1009
+ soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = {
1010
+ '\x00': '\\x00',
1011
+ '\x08': '\\x08',
1012
+ '\x09': '\\t',
1013
+ '\x0a': '\\n',
1014
+ '\x0b': '\\x0b',
1015
+ '\x0c': '\\f',
1016
+ '\x0d': '\\r',
1017
+ '\x22': '\\x22',
1018
+ '\x26': '\\x26',
1019
+ '\x27': '\\x27',
1020
+ '\/': '\\\/',
1021
+ '\x3c': '\\x3c',
1022
+ '\x3d': '\\x3d',
1023
+ '\x3e': '\\x3e',
1024
+ '\\': '\\\\',
1025
+ '\x85': '\\x85',
1026
+ '\u2028': '\\u2028',
1027
+ '\u2029': '\\u2029',
1028
+ '$': '\\x24',
1029
+ '(': '\\x28',
1030
+ ')': '\\x29',
1031
+ '*': '\\x2a',
1032
+ '+': '\\x2b',
1033
+ ',': '\\x2c',
1034
+ '-': '\\x2d',
1035
+ '.': '\\x2e',
1036
+ ':': '\\x3a',
1037
+ '?': '\\x3f',
1038
+ '[': '\\x5b',
1039
+ ']': '\\x5d',
1040
+ '^': '\\x5e',
1041
+ '{': '\\x7b',
1042
+ '|': '\\x7c',
1043
+ '}': '\\x7d'
1044
+ };
1045
+
1046
+ /**
1047
+ * A function that can be used with String.replace..
1048
+ * @param {string} ch A single character matched by a compatible matcher.
1049
+ * @return {string} A token in the output language.
1050
+ * @private
1051
+ */
1052
+ soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = function(ch) {
1053
+ return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_[ch];
1054
+ };
1055
+
1056
+ /**
1057
+ * Maps charcters to the escaped versions for the named escape directives.
1058
+ * @type {Object.<string, string>}
1059
+ * @private
1060
+ */
1061
+ soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_ = {
1062
+ '\x00': '\\0 ',
1063
+ '\x08': '\\8 ',
1064
+ '\x09': '\\9 ',
1065
+ '\x0a': '\\a ',
1066
+ '\x0b': '\\b ',
1067
+ '\x0c': '\\c ',
1068
+ '\x0d': '\\d ',
1069
+ '\x22': '\\22 ',
1070
+ '\x26': '\\26 ',
1071
+ '\x27': '\\27 ',
1072
+ '(': '\\28 ',
1073
+ ')': '\\29 ',
1074
+ '*': '\\2a ',
1075
+ '\/': '\\2f ',
1076
+ ':': '\\3a ',
1077
+ ';': '\\3b ',
1078
+ '\x3c': '\\3c ',
1079
+ '\x3d': '\\3d ',
1080
+ '\x3e': '\\3e ',
1081
+ '@': '\\40 ',
1082
+ '\\': '\\5c ',
1083
+ '{': '\\7b ',
1084
+ '}': '\\7d ',
1085
+ '\x85': '\\85 ',
1086
+ '\xa0': '\\a0 ',
1087
+ '\u2028': '\\2028 ',
1088
+ '\u2029': '\\2029 '
1089
+ };
1090
+
1091
+ /**
1092
+ * A function that can be used with String.replace..
1093
+ * @param {string} ch A single character matched by a compatible matcher.
1094
+ * @return {string} A token in the output language.
1095
+ * @private
1096
+ */
1097
+ soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_ = function(ch) {
1098
+ return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_[ch];
1099
+ };
1100
+
1101
+ /**
1102
+ * Maps charcters to the escaped versions for the named escape directives.
1103
+ * @type {Object.<string, string>}
1104
+ * @private
1105
+ */
1106
+ soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = {
1107
+ '\x00': '%00',
1108
+ '\x01': '%01',
1109
+ '\x02': '%02',
1110
+ '\x03': '%03',
1111
+ '\x04': '%04',
1112
+ '\x05': '%05',
1113
+ '\x06': '%06',
1114
+ '\x07': '%07',
1115
+ '\x08': '%08',
1116
+ '\x09': '%09',
1117
+ '\x0a': '%0A',
1118
+ '\x0b': '%0B',
1119
+ '\x0c': '%0C',
1120
+ '\x0d': '%0D',
1121
+ '\x0e': '%0E',
1122
+ '\x0f': '%0F',
1123
+ '\x10': '%10',
1124
+ '\x11': '%11',
1125
+ '\x12': '%12',
1126
+ '\x13': '%13',
1127
+ '\x14': '%14',
1128
+ '\x15': '%15',
1129
+ '\x16': '%16',
1130
+ '\x17': '%17',
1131
+ '\x18': '%18',
1132
+ '\x19': '%19',
1133
+ '\x1a': '%1A',
1134
+ '\x1b': '%1B',
1135
+ '\x1c': '%1C',
1136
+ '\x1d': '%1D',
1137
+ '\x1e': '%1E',
1138
+ '\x1f': '%1F',
1139
+ ' ': '%20',
1140
+ '\x22': '%22',
1141
+ '\x27': '%27',
1142
+ '(': '%28',
1143
+ ')': '%29',
1144
+ '\x3c': '%3C',
1145
+ '\x3e': '%3E',
1146
+ '\\': '%5C',
1147
+ '{': '%7B',
1148
+ '}': '%7D',
1149
+ '\x7f': '%7F',
1150
+ '\x85': '%C2%85',
1151
+ '\xa0': '%C2%A0',
1152
+ '\u2028': '%E2%80%A8',
1153
+ '\u2029': '%E2%80%A9',
1154
+ '\uff01': '%EF%BC%81',
1155
+ '\uff03': '%EF%BC%83',
1156
+ '\uff04': '%EF%BC%84',
1157
+ '\uff06': '%EF%BC%86',
1158
+ '\uff07': '%EF%BC%87',
1159
+ '\uff08': '%EF%BC%88',
1160
+ '\uff09': '%EF%BC%89',
1161
+ '\uff0a': '%EF%BC%8A',
1162
+ '\uff0b': '%EF%BC%8B',
1163
+ '\uff0c': '%EF%BC%8C',
1164
+ '\uff0f': '%EF%BC%8F',
1165
+ '\uff1a': '%EF%BC%9A',
1166
+ '\uff1b': '%EF%BC%9B',
1167
+ '\uff1d': '%EF%BC%9D',
1168
+ '\uff1f': '%EF%BC%9F',
1169
+ '\uff20': '%EF%BC%A0',
1170
+ '\uff3b': '%EF%BC%BB',
1171
+ '\uff3d': '%EF%BC%BD'
1172
+ };
1173
+
1174
+ /**
1175
+ * A function that can be used with String.replace..
1176
+ * @param {string} ch A single character matched by a compatible matcher.
1177
+ * @return {string} A token in the output language.
1178
+ * @private
1179
+ */
1180
+ soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = function(ch) {
1181
+ return soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_[ch];
1182
+ };
1183
+
1184
+ /**
1185
+ * Matches characters that need to be escaped for the named directives.
1186
+ * @type RegExp
1187
+ * @private
1188
+ */
1189
+ soy.esc.$$MATCHER_FOR_ESCAPE_HTML_ = /[\x00\x22\x26\x27\x3c\x3e]/g;
1190
+
1191
+ /**
1192
+ * Matches characters that need to be escaped for the named directives.
1193
+ * @type RegExp
1194
+ * @private
1195
+ */
1196
+ soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_ = /[\x00\x22\x27\x3c\x3e]/g;
1197
+
1198
+ /**
1199
+ * Matches characters that need to be escaped for the named directives.
1200
+ * @type RegExp
1201
+ * @private
1202
+ */
1203
+ soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x26\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g;
1204
+
1205
+ /**
1206
+ * Matches characters that need to be escaped for the named directives.
1207
+ * @type RegExp
1208
+ * @private
1209
+ */
1210
+ soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g;
1211
+
1212
+ /**
1213
+ * Matches characters that need to be escaped for the named directives.
1214
+ * @type RegExp
1215
+ * @private
1216
+ */
1217
+ soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_ = /[\x00\x08-\x0d\x22\x26\x27\/\x3c-\x3e\\\x85\u2028\u2029]/g;
1218
+
1219
+ /**
1220
+ * Matches characters that need to be escaped for the named directives.
1221
+ * @type RegExp
1222
+ * @private
1223
+ */
1224
+ soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_ = /[\x00\x08-\x0d\x22\x24\x26-\/\x3a\x3c-\x3f\x5b-\x5e\x7b-\x7d\x85\u2028\u2029]/g;
1225
+
1226
+ /**
1227
+ * Matches characters that need to be escaped for the named directives.
1228
+ * @type RegExp
1229
+ * @private
1230
+ */
1231
+ soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_ = /[\x00\x08-\x0d\x22\x26-\x2a\/\x3a-\x3e@\\\x7b\x7d\x85\xa0\u2028\u2029]/g;
1232
+
1233
+ /**
1234
+ * Matches characters that need to be escaped for the named directives.
1235
+ * @type RegExp
1236
+ * @private
1237
+ */
1238
+ 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;
1239
+
1240
+ /**
1241
+ * A pattern that vets values produced by the named directives.
1242
+ * @type RegExp
1243
+ * @private
1244
+ */
1245
+ 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;
1246
+
1247
+ /**
1248
+ * A pattern that vets values produced by the named directives.
1249
+ * @type RegExp
1250
+ * @private
1251
+ */
1252
+ soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_ = /^(?:(?:https?|mailto):|[^&:\/?#]*(?:[\/?#]|$))/i;
1253
+
1254
+ /**
1255
+ * A pattern that vets values produced by the named directives.
1256
+ * @type RegExp
1257
+ * @private
1258
+ */
1259
+ 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;
1260
+
1261
+ /**
1262
+ * A pattern that vets values produced by the named directives.
1263
+ * @type RegExp
1264
+ * @private
1265
+ */
1266
+ soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_ = /^(?!script|style|title|textarea|xmp|no)[a-z0-9_$:-]*$/i;
1267
+
1268
+ /**
1269
+ * A helper for the Soy directive |escapeHtml
1270
+ * @param {*} value Can be of any type but will be coerced to a string.
1271
+ * @return {string} The escaped text.
1272
+ */
1273
+ soy.esc.$$escapeHtmlHelper = function(value) {
1274
+ var str = String(value);
1275
+ return str.replace(
1276
+ soy.esc.$$MATCHER_FOR_ESCAPE_HTML_,
1277
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
1278
+ };
1279
+
1280
+ /**
1281
+ * A helper for the Soy directive |normalizeHtml
1282
+ * @param {*} value Can be of any type but will be coerced to a string.
1283
+ * @return {string} The escaped text.
1284
+ */
1285
+ soy.esc.$$normalizeHtmlHelper = function(value) {
1286
+ var str = String(value);
1287
+ return str.replace(
1288
+ soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_,
1289
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
1290
+ };
1291
+
1292
+ /**
1293
+ * A helper for the Soy directive |escapeHtmlNospace
1294
+ * @param {*} value Can be of any type but will be coerced to a string.
1295
+ * @return {string} The escaped text.
1296
+ */
1297
+ soy.esc.$$escapeHtmlNospaceHelper = function(value) {
1298
+ var str = String(value);
1299
+ return str.replace(
1300
+ soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_,
1301
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
1302
+ };
1303
+
1304
+ /**
1305
+ * A helper for the Soy directive |normalizeHtmlNospace
1306
+ * @param {*} value Can be of any type but will be coerced to a string.
1307
+ * @return {string} The escaped text.
1308
+ */
1309
+ soy.esc.$$normalizeHtmlNospaceHelper = function(value) {
1310
+ var str = String(value);
1311
+ return str.replace(
1312
+ soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_,
1313
+ soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
1314
+ };
1315
+
1316
+ /**
1317
+ * A helper for the Soy directive |escapeJsString
1318
+ * @param {*} value Can be of any type but will be coerced to a string.
1319
+ * @return {string} The escaped text.
1320
+ */
1321
+ soy.esc.$$escapeJsStringHelper = function(value) {
1322
+ var str = String(value);
1323
+ return str.replace(
1324
+ soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_,
1325
+ soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_);
1326
+ };
1327
+
1328
+ /**
1329
+ * A helper for the Soy directive |escapeJsRegex
1330
+ * @param {*} value Can be of any type but will be coerced to a string.
1331
+ * @return {string} The escaped text.
1332
+ */
1333
+ soy.esc.$$escapeJsRegexHelper = function(value) {
1334
+ var str = String(value);
1335
+ return str.replace(
1336
+ soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_,
1337
+ soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_);
1338
+ };
1339
+
1340
+ /**
1341
+ * A helper for the Soy directive |escapeCssString
1342
+ * @param {*} value Can be of any type but will be coerced to a string.
1343
+ * @return {string} The escaped text.
1344
+ */
1345
+ soy.esc.$$escapeCssStringHelper = function(value) {
1346
+ var str = String(value);
1347
+ return str.replace(
1348
+ soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_,
1349
+ soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_);
1350
+ };
1351
+
1352
+ /**
1353
+ * A helper for the Soy directive |filterCssValue
1354
+ * @param {*} value Can be of any type but will be coerced to a string.
1355
+ * @return {string} The escaped text.
1356
+ */
1357
+ soy.esc.$$filterCssValueHelper = function(value) {
1358
+ var str = String(value);
1359
+ if (!soy.esc.$$FILTER_FOR_FILTER_CSS_VALUE_.test(str)) {
1360
+ goog.asserts.fail('Bad value `%s` for |filterCssValue', [str]);
1361
+ return 'zSoyz';
1362
+ }
1363
+ return str;
1364
+ };
1365
+
1366
+ /**
1367
+ * A helper for the Soy directive |normalizeUri
1368
+ * @param {*} value Can be of any type but will be coerced to a string.
1369
+ * @return {string} The escaped text.
1370
+ */
1371
+ soy.esc.$$normalizeUriHelper = function(value) {
1372
+ var str = String(value);
1373
+ return str.replace(
1374
+ soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_,
1375
+ soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_);
1376
+ };
1377
+
1378
+ /**
1379
+ * A helper for the Soy directive |filterNormalizeUri
1380
+ * @param {*} value Can be of any type but will be coerced to a string.
1381
+ * @return {string} The escaped text.
1382
+ */
1383
+ soy.esc.$$filterNormalizeUriHelper = function(value) {
1384
+ var str = String(value);
1385
+ if (!soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_.test(str)) {
1386
+ goog.asserts.fail('Bad value `%s` for |filterNormalizeUri', [str]);
1387
+ return 'zSoyz';
1388
+ }
1389
+ return str.replace(
1390
+ soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_,
1391
+ soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_);
1392
+ };
1393
+
1394
+ /**
1395
+ * A helper for the Soy directive |filterHtmlAttribute
1396
+ * @param {*} value Can be of any type but will be coerced to a string.
1397
+ * @return {string} The escaped text.
1398
+ */
1399
+ soy.esc.$$filterHtmlAttributeHelper = function(value) {
1400
+ var str = String(value);
1401
+ if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ATTRIBUTE_.test(str)) {
1402
+ goog.asserts.fail('Bad value `%s` for |filterHtmlAttribute', [str]);
1403
+ return 'zSoyz';
1404
+ }
1405
+ return str;
1406
+ };
1407
+
1408
+ /**
1409
+ * A helper for the Soy directive |filterHtmlElementName
1410
+ * @param {*} value Can be of any type but will be coerced to a string.
1411
+ * @return {string} The escaped text.
1412
+ */
1413
+ soy.esc.$$filterHtmlElementNameHelper = function(value) {
1414
+ var str = String(value);
1415
+ if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_.test(str)) {
1416
+ goog.asserts.fail('Bad value `%s` for |filterHtmlElementName', [str]);
1417
+ return 'zSoyz';
1418
+ }
1419
+ return str;
1420
+ };
1421
+
1422
+ /**
1423
+ * Matches all tags, HTML comments, and DOCTYPEs in tag soup HTML.
1424
+ *
1425
+ * @type {RegExp}
1426
+ * @private
1427
+ */
1428
+ soy.esc.$$HTML_TAG_REGEX_ = /<(?:!|\/?[a-zA-Z])(?:[^>'"]|"[^"]*"|'[^']*')*>/g;
1429
+
1430
+ // END GENERATED CODE
1431
+ ;
1432
+ ;
1433
+ FI"asset_paths;
1434
+ F["l/Volumes/Development/dev-web/gems/yellow-brick-road/vendor/closure-soyutils-usegoog/soyutils_usegoog.jsI"dependency_paths;
1435
+ F[{I" path;
1436
+ F"l/Volumes/Development/dev-web/gems/yellow-brick-road/vendor/closure-soyutils-usegoog/soyutils_usegoog.jsI"
1437
+ mtime;
1438
+ FIu: Time
1439
+ T: offsetiI"hexdigest;
1440
+ F"%b1c876fa49eea9e978577bf928e5c568I"
1441
+ F"%46dde6621c301f4928e3b34efee9e3b5