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.
- data/README.md +142 -9
- data/bin/closure-script +19 -0
- data/closure-compiler/README +18 -4
- data/closure-compiler/compiler.jar +0 -0
- data/closure-templates/SoyToJsSrcCompiler.jar +0 -0
- data/closure-templates/soydata.js +163 -0
- data/closure-templates/soyutils.js +1191 -159
- data/closure-templates/soyutils_usegoog.js +1107 -60
- data/docs/closure/Closure.html +58 -52
- data/docs/closure/Closure/BeanShell.html +6 -3
- data/docs/closure/Closure/Compiler.html +18 -15
- data/docs/closure/Closure/Compiler/Compilation.html +9 -3
- data/docs/closure/Closure/Compiler/Error.html +3 -3
- data/docs/closure/Closure/FileResponse.html +13 -7
- data/docs/closure/Closure/Goog.html +49 -85
- data/docs/closure/Closure/Middleware.html +5 -3
- data/docs/closure/Closure/Script.html +14 -5
- data/docs/closure/Closure/Script/NotFound.html +3 -3
- data/docs/closure/Closure/Script/RenderStackOverflow.html +3 -3
- data/docs/closure/Closure/Server.html +6 -3
- data/docs/closure/Closure/ShowExceptions.html +5 -3
- data/docs/closure/Closure/Sources.html +145 -37
- data/docs/closure/Closure/Templates.html +11 -10
- data/docs/closure/Closure/Templates/Error.html +3 -3
- data/docs/closure/_index.html +4 -4
- data/docs/closure/css/full_list.css +2 -0
- data/docs/closure/css/style.css +2 -0
- data/docs/closure/file.LICENSE.html +3 -3
- data/docs/closure/file.README.html +151 -10
- data/docs/closure/frames.html +1 -1
- data/docs/closure/index.html +151 -10
- data/docs/closure/js/full_list.js +23 -6
- data/docs/closure/method_list.html +91 -83
- data/docs/closure/top-level-namespace.html +3 -3
- data/lib/closure.rb +3 -16
- data/lib/closure/compiler.rb +135 -53
- data/lib/closure/goog.rb +5 -29
- data/lib/closure/sources.rb +22 -9
- data/lib/closure/version.rb +1 -1
- data/scripts/config.ru +0 -1
- data/scripts/hello/compiler_build.js +5 -5
- data/scripts/hello/compiler_build.map +518 -522
- data/scripts/hello/compiler_debug.js +7 -13
- data/scripts/hello/legume.js +2 -2
- data/scripts/index.erb +0 -3
- data/scripts/modules/compiler_build.js +3 -3
- data/scripts/modules/compiler_build.map +11569 -11476
- data/scripts/modules/compiler_build_api.js +1 -1
- data/scripts/modules/compiler_build_app.js +71 -70
- data/scripts/modules/compiler_build_settings.js +2 -2
- data/scripts/modules/compiler_debug.js +3 -3
- data/scripts/modules/compiler_debug_api.js +2 -2
- data/scripts/modules/compiler_debug_app.js +926 -1382
- data/scripts/modules/compiler_debug_settings.js +21 -24
- metadata +8 -18
- data/externs/chrome_extensions.externs +0 -968
- data/externs/jquery-1.3.2.externs +0 -718
- data/externs/jquery-1.4.3.externs +0 -1289
- data/externs/jquery-1.4.4.externs +0 -1302
- data/externs/jquery-1.5.externs +0 -1697
- data/externs/jquery-ui.externs +0 -10
- data/externs/jquery.externs +0 -4
- data/scripts/jquery/compiler.js.erb +0 -7
- data/scripts/jquery/compiler_out.js +0 -1
- data/scripts/jquery/index.erb +0 -25
- data/scripts/jquery/jquery_1.4.4.js +0 -167
- data/scripts/jquery/jquery_test.js +0 -8
data/README.md
CHANGED
@@ -1,14 +1,147 @@
|
|
1
|
-
|
1
|
+
# Closure Script
|
2
|
+
|
3
|
+
A development environment for Google Closure Tools.
|
2
4
|
|
3
5
|
Licensed under the Apache License, Version 2.0 (the "License");
|
4
6
|
<http://www.apache.org/licenses/LICENSE-2.0>
|
5
7
|
|
8
|
+
# Installing
|
9
|
+
|
10
|
+
Everything you need for advanced Google Closure development is available in a
|
11
|
+
single .jar for the Java Virtual Machine. You may also run the tools on any
|
12
|
+
Ruby platform (>=1.8.6) including JRuby (JVM), Rubinius (LLVM), and Ruby 1.9 (YARV).
|
13
|
+
|
14
|
+
It is generally easier to get started with the .jar distribution, especially
|
15
|
+
under Windows. Mac OSX and most Linux will have a compatible Ruby by default.
|
16
|
+
|
17
|
+
## Java (.jar)
|
18
|
+
|
19
|
+
### Step 1: Download to a new folder
|
20
|
+
|
21
|
+
cd ~/empty-dir
|
22
|
+
curl -LO https://github.com/downloads/dturnbull/closure-script/closure-1.4.2.jar
|
23
|
+
|
24
|
+
### Step 2: Start server from the new folder
|
25
|
+
|
26
|
+
java -jar closure-1.4.2.jar
|
27
|
+
|
28
|
+
### Step 3: Open a web browser
|
29
|
+
|
30
|
+
http://localhost:8080/
|
31
|
+
|
32
|
+
|
33
|
+
## Ruby (.gem)
|
34
|
+
|
35
|
+
### Step 1: Install the gem
|
36
|
+
|
37
|
+
gem install closure
|
38
|
+
|
39
|
+
### Step 2: Start server from a new folder
|
40
|
+
|
41
|
+
cd ~/empty-dir
|
42
|
+
closure-script
|
43
|
+
|
44
|
+
### Step 3: Open a web browser
|
45
|
+
|
46
|
+
http://localhost:8080/
|
47
|
+
|
48
|
+
|
49
|
+
# The Closure Script Method
|
50
|
+
|
51
|
+
When you start the server for the first time in an empty folder, the home page
|
52
|
+
will prompt you to install scaffolding. This includes three example projects to
|
53
|
+
demonstrate soy, modules, and unobtrusive markup. Dissecting and working with
|
54
|
+
these examples is the fast track to understanding The Closure Script Method.
|
55
|
+
|
56
|
+
## The Server
|
57
|
+
|
58
|
+
Closure Script is a high-performance, multi-threaded web application engineered
|
59
|
+
exclusively for the needs of Google Closure Javascript development.
|
60
|
+
|
61
|
+
You will be freed from the command line. All error output from the compiler
|
62
|
+
will show on the Javascript console. This avoids lost time from not being
|
63
|
+
in the correct log and missing an important error. Javascript compilation
|
64
|
+
is done just-in-time and only when source files have changed.
|
65
|
+
No need for a separate build step; just refresh the browser. Not working?
|
66
|
+
Check your Javascript console. Then back to your editor.
|
67
|
+
|
68
|
+
## Easy Configuration
|
69
|
+
|
70
|
+
You'll need to supply the directories where you have source Javascript and static files.
|
71
|
+
Ruby developers will recognize that Closure Script is Rack middleware. This makes it trivial
|
72
|
+
to include the Closure Script build tool in a Rails application. If you're not developing a
|
73
|
+
Ruby application, your ```config.ru``` will probably never be more complex than the following:
|
74
|
+
|
75
|
+
require 'closure'
|
76
|
+
Closure.add_source '.', '/'
|
77
|
+
use Closure::Middleware, 'index'
|
78
|
+
run Rack::File.new '.'
|
79
|
+
|
80
|
+
The add_source command may be duplicated for each source Javascript folder you want to
|
81
|
+
serve. The first argument is the local filesystem path, the second is the mount point
|
82
|
+
for the http server. Make sure not to accidentally serve more than one copy of
|
83
|
+
Closure Library per Closure Script server or you'll get an error.
|
84
|
+
|
85
|
+
## Cut-and-Paste Ruby
|
86
|
+
|
87
|
+
In practice, all you do with Ruby is adjust the arguments to compiler.jar by
|
88
|
+
analyzing options on the URL query string. If you can handle conditionally appending
|
89
|
+
strings to an array in Ruby, then you're fully qualified to use Closure Script!
|
90
|
+
There's enough example code in the scaffolding to cut-and-paste your way to victory.
|
91
|
+
|
92
|
+
### Demo Scripts
|
93
|
+
|
94
|
+
The Closure Script Method is to create various demo pages to drive development. You may
|
95
|
+
also choose to use your main application instead of Closure Script for your demo pages.
|
96
|
+
|
97
|
+
Files ending with .erb are Closure Scripts and will have their embedded Ruby evaluated
|
98
|
+
as they are served. Scripts may also render other Scripts and pass variables if you
|
99
|
+
need that complexity. Scripts default to a MIME type of text/html so ```demo.erb``` is
|
100
|
+
the same as ```demo.html.erb```.
|
101
|
+
|
102
|
+
<html>
|
103
|
+
<head>
|
104
|
+
<script src='compiler.js?<%= query_string %>'></script>
|
105
|
+
</head>
|
106
|
+
|
107
|
+
### Compiler Scripts
|
108
|
+
|
109
|
+
Compilation is performed by requesting a file that generates Javascript instead of HTML.
|
110
|
+
The goog.compile() function of Closure Script handles everything for you.
|
111
|
+
|
112
|
+
Note that goog.compile() does not simply call the compiler. It will monitor your source
|
113
|
+
files and skip calling the compiler if everything is up to date. The Java process will
|
114
|
+
remain running on a REPL so subsequent compilations don't pay the Java startup cost.
|
115
|
+
The dependency tree for all your sources is known so you can build from namespaces
|
116
|
+
(--ns) as well as files (--js). Modules have been automated to find common dependencies,
|
117
|
+
like plovr, and work from namespaces so you don't need to use filenames and counts.
|
118
|
+
The luxurious goog.compile() can serve up a loader for the raw, uncompiled files,
|
119
|
+
even when working with modules.
|
120
|
+
|
121
|
+
A very simple compiler.js.erb is as follows. Check the scaffold for practical examples
|
122
|
+
that use the query string.
|
123
|
+
|
124
|
+
<%
|
125
|
+
args = %w{
|
126
|
+
--compilation_level ADVANCED_OPTIMIZATIONS
|
127
|
+
--js_output_file compiler_build.js
|
128
|
+
--ns myapp.helloWorld
|
129
|
+
}
|
130
|
+
@response = goog.compile(args).to_response
|
131
|
+
%>
|
132
|
+
|
133
|
+
### Testing
|
134
|
+
|
135
|
+
Closure Script helps with testing because it can see your data in ways that
|
136
|
+
browsers are not allowed to. The ```alltests.js``` file in Closure Library is
|
137
|
+
generated by a program that scans the filesystem. Here's a replacement in
|
138
|
+
Closure Script so that a manual build step never has to be executed again:
|
6
139
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
140
|
+
<% all_test_files = Dir.glob expand_path '**/*_test.html'
|
141
|
+
json_strings = all_test_files.map { |x| relative_src(x).dump }
|
142
|
+
-%>var _allTests = [<%= json_strings.join(',') %>];
|
143
|
+
|
144
|
+
Since all of Ruby is at your disposal, you could even pull fixture data from SQL
|
145
|
+
or a web service. Perhaps a fixture refresh happens when the developer pushes a
|
146
|
+
form button. The svn.erb tool is a complex example that uses threads and a
|
147
|
+
background process. You're only limited by your imagination.
|
data/bin/closure-script
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
begin
|
3
|
+
require 'rubygems'
|
4
|
+
rescue LoadError
|
5
|
+
end
|
6
|
+
require 'rack'
|
7
|
+
closure_lib_path = File.expand_path('../lib', File.dirname(__FILE__))
|
8
|
+
if File.exist? File.join closure_lib_path, 'closure.rb'
|
9
|
+
$LOAD_PATH.unshift(closure_lib_path) if !$LOAD_PATH.include?(closure_lib_path)
|
10
|
+
end
|
11
|
+
if File.exist? 'config.ru'
|
12
|
+
Rack::Server.start
|
13
|
+
else
|
14
|
+
require 'closure'
|
15
|
+
ENV["CLOSURE_SCRIPT_WELCOME"] = 'true'
|
16
|
+
Rack::Server.start :config => File.join(Closure.base_path, 'scripts/config.ru')
|
17
|
+
end
|
18
|
+
|
19
|
+
|
data/closure-compiler/README
CHANGED
@@ -152,7 +152,7 @@ system have been added.
|
|
152
152
|
|
153
153
|
-----
|
154
154
|
Code in:
|
155
|
-
lib/
|
155
|
+
lib/rhino
|
156
156
|
|
157
157
|
Rhino
|
158
158
|
URL: http://www.mozilla.org/rhino
|
@@ -161,9 +161,8 @@ License: Netscape Public License and MPL / GPL dual license
|
|
161
161
|
|
162
162
|
Description: Mozilla Rhino is an implementation of JavaScript for the JVM.
|
163
163
|
|
164
|
-
Local Modifications:
|
165
|
-
|
166
|
-
http://code.google.com/p/jarjar/
|
164
|
+
Local Modifications: Minor changes to parsing JSDoc that usually get pushed
|
165
|
+
up-stream to Rhino trunk.
|
167
166
|
|
168
167
|
|
169
168
|
-----
|
@@ -210,6 +209,21 @@ Description: Annotations for software defect detection.
|
|
210
209
|
Local Modifications: None.
|
211
210
|
|
212
211
|
|
212
|
+
-----
|
213
|
+
Code in:
|
214
|
+
lib/jarjar.jar
|
215
|
+
|
216
|
+
Jar Jar Links
|
217
|
+
URL: http://jarjar.googlecode.com/
|
218
|
+
Version: 1.1
|
219
|
+
License: Apache License 2.0
|
220
|
+
|
221
|
+
Description:
|
222
|
+
A utility for repackaging Java libraries.
|
223
|
+
|
224
|
+
Local Modifications: None.
|
225
|
+
|
226
|
+
|
213
227
|
----
|
214
228
|
Code in:
|
215
229
|
lib/junit.jar
|
Binary file
|
Binary file
|
@@ -0,0 +1,163 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright 2010 Google Inc.
|
3
|
+
*
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
* you may not use this file except in compliance with the License.
|
6
|
+
* You may obtain a copy of the License at
|
7
|
+
*
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
*
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
* See the License for the specific language governing permissions and
|
14
|
+
* limitations under the License.
|
15
|
+
*/
|
16
|
+
|
17
|
+
|
18
|
+
/**
|
19
|
+
* @fileoverview
|
20
|
+
* Defines typed strings, e.g. an HTML string {@code "a<b>c"} is
|
21
|
+
* semantically distinct from the plain text string {@code "a<b>c"} and smart
|
22
|
+
* templates can take that distinction into account.
|
23
|
+
*
|
24
|
+
* @author Mike Samuel
|
25
|
+
*/
|
26
|
+
|
27
|
+
|
28
|
+
goog.provide('soydata');
|
29
|
+
goog.provide('soydata.SanitizedHtml');
|
30
|
+
goog.provide('soydata.SanitizedHtmlAttribute');
|
31
|
+
goog.provide('soydata.SanitizedJsStrChars');
|
32
|
+
goog.provide('soydata.SanitizedUri');
|
33
|
+
|
34
|
+
|
35
|
+
/**
|
36
|
+
* A type of textual content.
|
37
|
+
* @enum
|
38
|
+
*/
|
39
|
+
soydata.SanitizedContentKind = {
|
40
|
+
|
41
|
+
/**
|
42
|
+
* A snippet of HTML that does not start or end inside a tag, comment, entity,
|
43
|
+
* or DOCTYPE; and that does not contain any executable code
|
44
|
+
* (JS, {@code <object>}s, etc.) from a different trust domain.
|
45
|
+
*/
|
46
|
+
HTML: 0,
|
47
|
+
|
48
|
+
/**
|
49
|
+
* A sequence of code units that can appear between quotes (either kind) in a
|
50
|
+
* JS program without causing a parse error, and without causing any side
|
51
|
+
* effects.
|
52
|
+
* <p>
|
53
|
+
* The content should not contain unescaped quotes, newlines, or anything else
|
54
|
+
* that would cause parsing to fail or to cause a JS parser to finish the
|
55
|
+
* string its parsing inside the content.
|
56
|
+
* <p>
|
57
|
+
* The content must also not end inside an escape sequence ; no partial octal
|
58
|
+
* escape sequences or odd number of '{@code \}'s at the end.
|
59
|
+
*/
|
60
|
+
JS_STR_CHARS: 1,
|
61
|
+
|
62
|
+
/** A properly encoded portion of a URI. */
|
63
|
+
URI: 2,
|
64
|
+
|
65
|
+
/** An attribute name and value such as {@code dir="ltr"}. */
|
66
|
+
HTML_ATTRIBUTE: 3
|
67
|
+
};
|
68
|
+
|
69
|
+
|
70
|
+
/**
|
71
|
+
* A string-like object that carries a content-type.
|
72
|
+
* @constructor
|
73
|
+
* @private
|
74
|
+
*/
|
75
|
+
soydata.SanitizedContent = function() {};
|
76
|
+
|
77
|
+
/** The textual content. @type {string} */
|
78
|
+
soydata.SanitizedContent.prototype.content;
|
79
|
+
|
80
|
+
/** @type {soydata.SanitizedContentKind} */
|
81
|
+
soydata.SanitizedContent.prototype.contentKind;
|
82
|
+
|
83
|
+
/**
|
84
|
+
* @return {string}
|
85
|
+
*/
|
86
|
+
soydata.SanitizedContent.prototype.toString = function() {
|
87
|
+
return this.content;
|
88
|
+
};
|
89
|
+
|
90
|
+
|
91
|
+
/**
|
92
|
+
* Content of type {@link soydata.SanitizedContentKind.HTML}.
|
93
|
+
* @constructor
|
94
|
+
* @param {string!} content A string of HTML that can safely be embedded in
|
95
|
+
* a PCDATA context in your app. If you would be surprised to find that an
|
96
|
+
* HTML sanitizer produced {@code s} (e.g. it runs code or fetches bad URLs)
|
97
|
+
* and you wouldn't write a template that produces {@code s} on security or
|
98
|
+
* privacy grounds, then don't pass {@code s} here.
|
99
|
+
*/
|
100
|
+
soydata.SanitizedHtml = function(content) {
|
101
|
+
this.content = content;
|
102
|
+
};
|
103
|
+
|
104
|
+
/** @override */
|
105
|
+
soydata.SanitizedHtml.prototype = new soydata.SanitizedContent();
|
106
|
+
|
107
|
+
/** @override */
|
108
|
+
soydata.SanitizedHtml.prototype.contentKind = soydata.SanitizedContentKind.HTML;
|
109
|
+
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Content of type {@link soydata.SanitizedContentKind.JS_STR_CHARS}.
|
113
|
+
* @constructor
|
114
|
+
* @param {string!} content A string of JS that when evaled, produces a
|
115
|
+
* value that does not depend on any sensitive data and has no side effects
|
116
|
+
* <b>OR</b> a string of JS that does not reference any variables or have
|
117
|
+
* any side effects not known statically to the app authors.
|
118
|
+
*/
|
119
|
+
soydata.SanitizedJsStrChars = function(content) {
|
120
|
+
this.content = content;
|
121
|
+
};
|
122
|
+
|
123
|
+
/** @override */
|
124
|
+
soydata.SanitizedJsStrChars.prototype = new soydata.SanitizedContent();
|
125
|
+
|
126
|
+
/** @override */
|
127
|
+
soydata.SanitizedJsStrChars.prototype.contentKind =
|
128
|
+
soydata.SanitizedContentKind.JS_STR_CHARS;
|
129
|
+
|
130
|
+
|
131
|
+
/**
|
132
|
+
* Content of type {@link soydata.SanitizedContentKind.URI}.
|
133
|
+
* @constructor
|
134
|
+
* @param {string!} content A chunk of URI that the caller knows is safe to
|
135
|
+
* emit in a template.
|
136
|
+
*/
|
137
|
+
soydata.SanitizedUri = function(content) {
|
138
|
+
this.content = content;
|
139
|
+
};
|
140
|
+
|
141
|
+
/** @override */
|
142
|
+
soydata.SanitizedUri.prototype = new soydata.SanitizedContent();
|
143
|
+
|
144
|
+
/** @override */
|
145
|
+
soydata.SanitizedUri.prototype.contentKind = soydata.SanitizedContentKind.URI;
|
146
|
+
|
147
|
+
|
148
|
+
/**
|
149
|
+
* Content of type {@link soydata.SanitizedContentKind.HTML_ATTRIBUTE}.
|
150
|
+
* @constructor
|
151
|
+
* @param {string!} content An attribute name and value, such as
|
152
|
+
* {@code dir="ltr"}..
|
153
|
+
*/
|
154
|
+
soydata.SanitizedHtmlAttribute = function(content) {
|
155
|
+
this.content = content;
|
156
|
+
};
|
157
|
+
|
158
|
+
/** @override */
|
159
|
+
soydata.SanitizedHtmlAttribute.prototype = new soydata.SanitizedContent();
|
160
|
+
|
161
|
+
/** @override */
|
162
|
+
soydata.SanitizedHtmlAttribute.prototype.contentKind =
|
163
|
+
soydata.SanitizedContentKind.HTML_ATTRIBUTE;
|
@@ -14,16 +14,26 @@
|
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
/**
|
29
39
|
* Base name for the soy utilities, when used outside of Closure Library.
|
@@ -32,6 +42,7 @@
|
|
32
42
|
* @type {Object}
|
33
43
|
*/
|
34
44
|
var soy = soy || {};
|
45
|
+
soy.esc = soy.esc || {};
|
35
46
|
|
36
47
|
|
37
48
|
// Just enough browser detection for this file.
|
@@ -42,17 +53,17 @@ var soy = soy || {};
|
|
42
53
|
* @type {boolean}
|
43
54
|
* @private
|
44
55
|
*/
|
45
|
-
soy
|
56
|
+
soy.$$IS_OPERA_ = isOpera;
|
46
57
|
/**
|
47
58
|
* @type {boolean}
|
48
59
|
* @private
|
49
60
|
*/
|
50
|
-
soy
|
61
|
+
soy.$$IS_IE_ = !isOpera && ua.indexOf('MSIE') != -1;
|
51
62
|
/**
|
52
63
|
* @type {boolean}
|
53
64
|
* @private
|
54
65
|
*/
|
55
|
-
soy
|
66
|
+
soy.$$IS_WEBKIT_ = !isOpera && ua.indexOf('WebKit') != -1;
|
56
67
|
})();
|
57
68
|
|
58
69
|
|
@@ -67,7 +78,7 @@ var soy = soy || {};
|
|
67
78
|
*
|
68
79
|
* @param {Object|number|string|boolean=} opt_a1 Optional first initial item
|
69
80
|
* to append.
|
70
|
-
* @param {Object|number|string|boolean} var_args Other initial items to
|
81
|
+
* @param {...Object|number|string|boolean} var_args Other initial items to
|
71
82
|
* append, e.g., new soy.StringBuilder('foo', 'bar').
|
72
83
|
* @constructor
|
73
84
|
*/
|
@@ -78,7 +89,7 @@ soy.StringBuilder = function(opt_a1, var_args) {
|
|
78
89
|
* @type {string|Array}
|
79
90
|
* @private
|
80
91
|
*/
|
81
|
-
this.buffer_ = soy
|
92
|
+
this.buffer_ = soy.$$IS_IE_ ? [] : '';
|
82
93
|
|
83
94
|
if (opt_a1 != null) {
|
84
95
|
this.append.apply(this, arguments);
|
@@ -102,19 +113,20 @@ soy.StringBuilder.prototype.bufferLength_ = 0;
|
|
102
113
|
*
|
103
114
|
* @param {Object|number|string|boolean} a1 Required first string.
|
104
115
|
* @param {Object|number|string|boolean=} opt_a2 Optional second string.
|
105
|
-
* @param {Object|number|string|boolean} var_args Other items to append,
|
116
|
+
* @param {...Object|number|string|boolean} var_args Other items to append,
|
106
117
|
* e.g., sb.append('foo', 'bar', 'baz').
|
107
118
|
* @return {soy.StringBuilder} This same StringBuilder object.
|
108
119
|
*/
|
109
120
|
soy.StringBuilder.prototype.append = function(a1, opt_a2, var_args) {
|
110
121
|
|
111
|
-
if (soy
|
122
|
+
if (soy.$$IS_IE_) {
|
112
123
|
if (opt_a2 == null) { // no second argument (note: undefined == null)
|
113
124
|
// Array assignment is 2x faster than Array push. Also, use a1
|
114
125
|
// directly to avoid arguments instantiation, another 2x improvement.
|
115
126
|
this.buffer_[this.bufferLength_++] = a1;
|
116
127
|
} else {
|
117
|
-
this.buffer_
|
128
|
+
var arr = /**@type {Array.<number|string|boolean>}*/this.buffer_;
|
129
|
+
arr.push.apply(arr, arguments);
|
118
130
|
this.bufferLength_ = this.buffer_.length;
|
119
131
|
}
|
120
132
|
|
@@ -138,7 +150,7 @@ soy.StringBuilder.prototype.append = function(a1, opt_a2, var_args) {
|
|
138
150
|
*/
|
139
151
|
soy.StringBuilder.prototype.clear = function() {
|
140
152
|
|
141
|
-
if (soy
|
153
|
+
if (soy.$$IS_IE_) {
|
142
154
|
this.buffer_.length = 0; // reuse array to avoid creating new object
|
143
155
|
this.bufferLength_ = 0;
|
144
156
|
|
@@ -155,7 +167,7 @@ soy.StringBuilder.prototype.clear = function() {
|
|
155
167
|
*/
|
156
168
|
soy.StringBuilder.prototype.toString = function() {
|
157
169
|
|
158
|
-
if (soy
|
170
|
+
if (soy.$$IS_IE_) {
|
159
171
|
var str = this.buffer_.join('');
|
160
172
|
// Given a string with the entire contents, simplify the StringBuilder by
|
161
173
|
// setting its contents to only be this string, rather than many fragments.
|
@@ -175,6 +187,16 @@ soy.StringBuilder.prototype.toString = function() {
|
|
175
187
|
// Public utilities.
|
176
188
|
|
177
189
|
|
190
|
+
/**
|
191
|
+
* Immutable object that is passed into templates that are rendered
|
192
|
+
* without any data.
|
193
|
+
*
|
194
|
+
* @type {Object}
|
195
|
+
* @private
|
196
|
+
*/
|
197
|
+
soy.$$DEFAULT_TEMPLATE_DATA_ = {};
|
198
|
+
|
199
|
+
|
178
200
|
/**
|
179
201
|
* Helper function to render a Soy template and then set the output string as
|
180
202
|
* the innerHTML of an element. It is recommended to use this helper function
|
@@ -184,35 +206,104 @@ soy.StringBuilder.prototype.toString = function() {
|
|
184
206
|
* @param {Element} element The element whose content we are rendering.
|
185
207
|
* @param {Function} template The Soy template defining the element's content.
|
186
208
|
* @param {Object=} opt_templateData The data for the template.
|
209
|
+
* @param {Object=} opt_injectedData The injected data for the template.
|
187
210
|
*/
|
188
|
-
soy.renderElement = function(
|
189
|
-
|
211
|
+
soy.renderElement = function(
|
212
|
+
element, template, opt_templateData, opt_injectedData) {
|
213
|
+
element.innerHTML = template(
|
214
|
+
opt_templateData || soy.$$DEFAULT_TEMPLATE_DATA_, undefined,
|
215
|
+
opt_injectedData);
|
190
216
|
};
|
191
217
|
|
192
218
|
|
193
219
|
/**
|
194
220
|
* Helper function to render a Soy template into a single node or a document
|
195
221
|
* fragment. If the rendered HTML string represents a single node, then that
|
196
|
-
* node is returned
|
222
|
+
* node is returned (note that this is *not* a fragment, despite them name of
|
223
|
+
* the method). Otherwise a document fragment is returned containing the
|
197
224
|
* rendered nodes.
|
198
225
|
*
|
199
226
|
* @param {Function} template The Soy template defining the element's content.
|
200
227
|
* @param {Object=} opt_templateData The data for the template.
|
201
|
-
* @
|
228
|
+
* @param {Document=} opt_document The document used to create DOM nodes. If not
|
229
|
+
* specified, global document object is used.
|
230
|
+
* @param {Object=} opt_injectedData The injected data for the template.
|
231
|
+
* @return {!Node} The resulting node or document fragment.
|
202
232
|
*/
|
203
|
-
soy.renderAsFragment = function(
|
233
|
+
soy.renderAsFragment = function(
|
234
|
+
template, opt_templateData, opt_document, opt_injectedData) {
|
235
|
+
return soy.$$renderWithWrapper_(
|
236
|
+
template, opt_templateData, opt_document, false /* asElement */,
|
237
|
+
opt_injectedData);
|
238
|
+
};
|
204
239
|
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
240
|
+
|
241
|
+
/**
|
242
|
+
* Helper function to render a Soy template into a single node. If the rendered
|
243
|
+
* HTML string represents a single node, then that node is returned. Otherwise,
|
244
|
+
* a DIV element is returned containing the rendered nodes.
|
245
|
+
*
|
246
|
+
* @param {Function} template The Soy template defining the element's content.
|
247
|
+
* @param {Object=} opt_templateData The data for the template.
|
248
|
+
* @param {Document=} opt_document The document used to create DOM nodes. If not
|
249
|
+
* specified, global document object is used.
|
250
|
+
* @param {Object=} opt_injectedData The injected data for the template.
|
251
|
+
* @return {!Element} Rendered template contents, wrapped in a parent DIV
|
252
|
+
* element if necessary.
|
253
|
+
*/
|
254
|
+
soy.renderAsElement = function(
|
255
|
+
template, opt_templateData, opt_document, opt_injectedData) {
|
256
|
+
return /** @type {!Element} */ (soy.$$renderWithWrapper_(
|
257
|
+
template, opt_templateData, opt_document, true /* asElement */,
|
258
|
+
opt_injectedData));
|
259
|
+
};
|
260
|
+
|
261
|
+
|
262
|
+
/**
|
263
|
+
* Helper function to render a Soy template into a single node or a document
|
264
|
+
* fragment. If the rendered HTML string represents a single node, then that
|
265
|
+
* node is returned. Otherwise a document fragment is created and returned
|
266
|
+
* (wrapped in a DIV element if #opt_singleNode is true).
|
267
|
+
*
|
268
|
+
* @param {Function} template The Soy template defining the element's content.
|
269
|
+
* @param {Object=} opt_templateData The data for the template.
|
270
|
+
* @param {Document=} opt_document The document used to create DOM nodes. If not
|
271
|
+
* specified, global document object is used.
|
272
|
+
* @param {boolean=} opt_asElement Whether to wrap the fragment in an
|
273
|
+
* element if the template does not render a single element. If true, result
|
274
|
+
* is always an Element.
|
275
|
+
* @param {Object=} opt_injectedData The injected data for the template.
|
276
|
+
* @return {!Node} The resulting node or document fragment.
|
277
|
+
* @private
|
278
|
+
*/
|
279
|
+
soy.$$renderWithWrapper_ = function(
|
280
|
+
template, opt_templateData, opt_document, opt_asElement, opt_injectedData) {
|
281
|
+
|
282
|
+
var doc = opt_document || document;
|
283
|
+
var wrapper = doc.createElement('div');
|
284
|
+
wrapper.innerHTML = template(
|
285
|
+
opt_templateData || soy.$$DEFAULT_TEMPLATE_DATA_, undefined,
|
286
|
+
opt_injectedData);
|
287
|
+
|
288
|
+
// If the template renders as a single element, return it.
|
289
|
+
if (wrapper.childNodes.length == 1) {
|
290
|
+
var firstChild = wrapper.firstChild;
|
291
|
+
if (!opt_asElement || firstChild.nodeType == 1 /* Element */) {
|
292
|
+
return /** @type {!Node} */ (firstChild);
|
213
293
|
}
|
214
|
-
return fragment;
|
215
294
|
}
|
295
|
+
|
296
|
+
// If we're forcing it to be a single element, return the wrapper DIV.
|
297
|
+
if (opt_asElement) {
|
298
|
+
return wrapper;
|
299
|
+
}
|
300
|
+
|
301
|
+
// Otherwise, create and return a fragment.
|
302
|
+
var fragment = doc.createDocumentFragment();
|
303
|
+
while (wrapper.firstChild) {
|
304
|
+
fragment.appendChild(wrapper.firstChild);
|
305
|
+
}
|
306
|
+
return fragment;
|
216
307
|
};
|
217
308
|
|
218
309
|
|
@@ -237,9 +328,9 @@ soy.$$augmentData = function(origData, additionalParams) {
|
|
237
328
|
|
238
329
|
// Create a new object whose '__proto__' field is set to origData.
|
239
330
|
/** @constructor */
|
240
|
-
function
|
241
|
-
|
242
|
-
var newData = new
|
331
|
+
function TempCtor() {}
|
332
|
+
TempCtor.prototype = origData;
|
333
|
+
var newData = new TempCtor();
|
243
334
|
|
244
335
|
// Add the additional params to the new object.
|
245
336
|
for (var key in additionalParams) {
|
@@ -251,151 +342,530 @@ soy.$$augmentData = function(origData, additionalParams) {
|
|
251
342
|
|
252
343
|
|
253
344
|
/**
|
254
|
-
*
|
345
|
+
* Gets the keys in a map as an array. There are no guarantees on the order.
|
346
|
+
* @param {Object} map The map to get the keys of.
|
347
|
+
* @return {Array.<string>} The array of keys in the given map.
|
348
|
+
*/
|
349
|
+
soy.$$getMapKeys = function(map) {
|
350
|
+
var mapKeys = [];
|
351
|
+
for (var key in map) {
|
352
|
+
mapKeys.push(key);
|
353
|
+
}
|
354
|
+
return mapKeys;
|
355
|
+
};
|
356
|
+
|
357
|
+
|
358
|
+
/**
|
359
|
+
* Gets a consistent unique id for the given delegate template name. Two calls
|
360
|
+
* to this function will return the same id if and only if the input names are
|
361
|
+
* the same.
|
362
|
+
*
|
363
|
+
* <p> Important: This function must always be called with a string constant.
|
364
|
+
*
|
365
|
+
* <p> If Closure Compiler is not being used, then this is just this identity
|
366
|
+
* function. If Closure Compiler is being used, then each call to this function
|
367
|
+
* will be replaced with a short string constant, which will be consistent per
|
368
|
+
* input name.
|
369
|
+
*
|
370
|
+
* @param {string} delTemplateName The delegate template name for which to get a
|
371
|
+
* consistent unique id.
|
372
|
+
* @return {string} A unique id that is consistent per input name.
|
373
|
+
*
|
374
|
+
* @consistentIdGenerator
|
375
|
+
*/
|
376
|
+
soy.$$getDelegateId = function(delTemplateName) {
|
377
|
+
return delTemplateName;
|
378
|
+
};
|
379
|
+
|
380
|
+
|
381
|
+
/**
|
382
|
+
* Map from registered delegate template id/name to the priority of the
|
383
|
+
* implementation.
|
384
|
+
* @type {Object}
|
385
|
+
* @private
|
386
|
+
*/
|
387
|
+
soy.$$DELEGATE_REGISTRY_PRIORITIES_ = {};
|
388
|
+
|
389
|
+
/**
|
390
|
+
* Map from registered delegate template id/name to the implementation function.
|
391
|
+
* @type {Object}
|
392
|
+
* @private
|
393
|
+
*/
|
394
|
+
soy.$$DELEGATE_REGISTRY_FUNCTIONS_ = {};
|
395
|
+
|
396
|
+
|
397
|
+
/**
|
398
|
+
* Registers a delegate implementation. If the same delegate template id/name
|
399
|
+
* has been registered previously, then priority values are compared and only
|
400
|
+
* the higher priority implementation is stored (if priorities are equal, an
|
401
|
+
* error is thrown).
|
402
|
+
*
|
403
|
+
* @param {string} delTemplateId The delegate template id/name to register.
|
404
|
+
* @param {number} delPriority The implementation's priority value.
|
405
|
+
* @param {Function} delFn The implementation function.
|
406
|
+
*/
|
407
|
+
soy.$$registerDelegateFn = function(delTemplateId, delPriority, delFn) {
|
408
|
+
var mapKey = 'key_' + delTemplateId;
|
409
|
+
var currPriority = soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey];
|
410
|
+
if (currPriority === undefined || delPriority > currPriority) {
|
411
|
+
// Registering new or higher-priority function: replace registry entry.
|
412
|
+
soy.$$DELEGATE_REGISTRY_PRIORITIES_[mapKey] = delPriority;
|
413
|
+
soy.$$DELEGATE_REGISTRY_FUNCTIONS_[mapKey] = delFn;
|
414
|
+
} else if (delPriority == currPriority) {
|
415
|
+
// Registering same-priority function: error.
|
416
|
+
throw Error(
|
417
|
+
'Encountered two active delegates with same priority (id/name "' +
|
418
|
+
delTemplateId + '").');
|
419
|
+
} else {
|
420
|
+
// Registering lower-priority function: do nothing.
|
421
|
+
}
|
422
|
+
};
|
423
|
+
|
424
|
+
|
425
|
+
/**
|
426
|
+
* Retrieves the (highest-priority) implementation that has been registered for
|
427
|
+
* a given delegate template id/name. If no implementation has been registered
|
428
|
+
* for the id/name, then returns an implementation that is equivalent to an
|
429
|
+
* empty template (i.e. rendered output would be empty string).
|
430
|
+
*
|
431
|
+
* @param {string} delTemplateId The delegate template id/name to get.
|
432
|
+
* @return {Function} The retrieved implementation function.
|
433
|
+
*/
|
434
|
+
soy.$$getDelegateFn = function(delTemplateId) {
|
435
|
+
var delFn = soy.$$DELEGATE_REGISTRY_FUNCTIONS_['key_' + delTemplateId];
|
436
|
+
return delFn ? delFn : soy.$$EMPTY_TEMPLATE_FN_;
|
437
|
+
};
|
438
|
+
|
439
|
+
|
440
|
+
/**
|
441
|
+
* Private helper soy.$$getDelegateFn(). This is the empty template function
|
442
|
+
* that is returned whenever there's no delegate implementation found.
|
443
|
+
*
|
444
|
+
* @param {Object.<string, *>=} opt_data
|
445
|
+
* @param {soy.StringBuilder=} opt_sb
|
446
|
+
* @param {Object.<string, *>=} opt_ijData
|
447
|
+
* @return {string}
|
448
|
+
* @private
|
449
|
+
*/
|
450
|
+
soy.$$EMPTY_TEMPLATE_FN_ = function(opt_data, opt_sb, opt_ijData) {
|
451
|
+
return '';
|
452
|
+
};
|
453
|
+
|
454
|
+
|
455
|
+
/**
|
456
|
+
* Used for temporary fix. See GenJsCodeVisitor.java.
|
457
|
+
* TODO: Remove when i18n plurals team provides a better # processing option.
|
458
|
+
* @param {string} str The string to escape.
|
459
|
+
* @return {string} The escaped string.
|
460
|
+
*/
|
461
|
+
soy.$$tempHashEscape = function(str) {
|
462
|
+
return str.replace(soy.$$HASH_RE_, '__HashLit__');
|
463
|
+
};
|
464
|
+
|
465
|
+
/**
|
466
|
+
* Used by soy.$$tempHashEscape().
|
467
|
+
* @type {RegExp}
|
468
|
+
* @private
|
469
|
+
*/
|
470
|
+
soy.$$HASH_RE_ = /#/g;
|
471
|
+
|
472
|
+
|
473
|
+
/**
|
474
|
+
* Used for temporary fix. See GenJsCodeVisitor.java.
|
475
|
+
* TODO: Remove when i18n plurals team provides a better # processing option.
|
476
|
+
* @param {string} str The string to unescape.
|
477
|
+
* @return {string} The unescaped string.
|
478
|
+
*/
|
479
|
+
soy.$$tempHashUnescape = function(str) {
|
480
|
+
return str.replace(soy.$$HASH_ESCAPED_RE_, '#');
|
481
|
+
};
|
482
|
+
|
483
|
+
/**
|
484
|
+
* Used by soy.$$tempHashUnescape().
|
485
|
+
* @type {RegExp}
|
486
|
+
* @private
|
487
|
+
*/
|
488
|
+
soy.$$HASH_ESCAPED_RE_ = /__HashLit__/g;
|
489
|
+
|
490
|
+
|
491
|
+
// -----------------------------------------------------------------------------
|
492
|
+
// Escape/filter/normalize.
|
493
|
+
|
494
|
+
|
495
|
+
/**
|
496
|
+
* Escapes HTML special characters in a string. Escapes double quote '"' in
|
255
497
|
* addition to '&', '<', and '>' so that a string can be included in an HTML
|
256
498
|
* tag attribute value within double quotes.
|
499
|
+
* Will emit known safe HTML as-is.
|
257
500
|
*
|
258
|
-
* @param {*}
|
259
|
-
* will be coerced to a string.
|
260
|
-
* @return {string} An escaped
|
261
|
-
*/
|
262
|
-
soy.$$escapeHtml = function(
|
501
|
+
* @param {*} value The string-like value to be escaped. May not be a string,
|
502
|
+
* but the value will be coerced to a string.
|
503
|
+
* @return {string} An escaped version of value.
|
504
|
+
*/
|
505
|
+
soy.$$escapeHtml = function(value) {
|
506
|
+
if (typeof value === 'object' && value &&
|
507
|
+
value.contentKind === soydata.SanitizedContentKind.HTML) {
|
508
|
+
return value.content;
|
509
|
+
}
|
510
|
+
return soy.esc.$$escapeHtmlHelper(value);
|
511
|
+
};
|
263
512
|
|
264
|
-
str = String(str);
|
265
513
|
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
514
|
+
/**
|
515
|
+
* Escapes HTML special characters in a string so that it can be embedded in
|
516
|
+
* RCDATA.
|
517
|
+
* <p>
|
518
|
+
* Escapes HTML special characters so that the value will not prematurely end
|
519
|
+
* the body of a tag like {@code <textarea>} or {@code <title>}. RCDATA tags
|
520
|
+
* cannot contain other HTML entities, so it is not strictly necessary to escape
|
521
|
+
* HTML special characters except when part of that text looks like an HTML
|
522
|
+
* entity or like a close tag : {@code </textarea>}.
|
523
|
+
* <p>
|
524
|
+
* Will normalize known safe HTML to make sure that sanitized HTML (which could
|
525
|
+
* contain an innocuous {@code </textarea>} don't prematurely end an RCDATA
|
526
|
+
* element.
|
527
|
+
*
|
528
|
+
* @param {*} value The string-like value to be escaped. May not be a string,
|
529
|
+
* but the value will be coerced to a string.
|
530
|
+
* @return {string} An escaped version of value.
|
531
|
+
*/
|
532
|
+
soy.$$escapeHtmlRcdata = function(value) {
|
533
|
+
if (typeof value === 'object' && value &&
|
534
|
+
value.contentKind === soydata.SanitizedContentKind.HTML) {
|
535
|
+
return soy.esc.$$normalizeHtmlHelper(value.content);
|
270
536
|
}
|
537
|
+
return soy.esc.$$escapeHtmlHelper(value);
|
538
|
+
};
|
271
539
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
540
|
+
|
541
|
+
/**
|
542
|
+
* Removes HTML tags from a string of known safe HTML so it can be used as an
|
543
|
+
* attribute value.
|
544
|
+
*
|
545
|
+
* @param {*} value The HTML to be escaped. May not be a string, but the
|
546
|
+
* value will be coerced to a string.
|
547
|
+
* @return {string} A representation of value without tags, HTML comments, or
|
548
|
+
* other content.
|
549
|
+
*/
|
550
|
+
soy.$$stripHtmlTags = function(value) {
|
551
|
+
return String(value).replace(soy.esc.$$HTML_TAG_REGEX_, '');
|
552
|
+
};
|
553
|
+
|
554
|
+
|
555
|
+
/**
|
556
|
+
* Escapes HTML special characters in an HTML attribute value.
|
557
|
+
*
|
558
|
+
* @param {*} value The HTML to be escaped. May not be a string, but the
|
559
|
+
* value will be coerced to a string.
|
560
|
+
* @return {string} An escaped version of value.
|
561
|
+
*/
|
562
|
+
soy.$$escapeHtmlAttribute = function(value) {
|
563
|
+
if (typeof value === 'object' && value &&
|
564
|
+
value.contentKind === soydata.SanitizedContentKind.HTML) {
|
565
|
+
return soy.esc.$$normalizeHtmlHelper(soy.$$stripHtmlTags(value.content));
|
279
566
|
}
|
280
|
-
|
281
|
-
|
567
|
+
return soy.esc.$$escapeHtmlHelper(value);
|
568
|
+
};
|
569
|
+
|
570
|
+
|
571
|
+
/**
|
572
|
+
* Escapes HTML special characters in a string including space and other
|
573
|
+
* characters that can end an unquoted HTML attribute value.
|
574
|
+
*
|
575
|
+
* @param {*} value The HTML to be escaped. May not be a string, but the
|
576
|
+
* value will be coerced to a string.
|
577
|
+
* @return {string} An escaped version of value.
|
578
|
+
*/
|
579
|
+
soy.$$escapeHtmlAttributeNospace = function(value) {
|
580
|
+
if (typeof value === 'object' && value &&
|
581
|
+
value.contentKind === soydata.SanitizedContentKind.HTML) {
|
582
|
+
return soy.esc.$$normalizeHtmlNospaceHelper(
|
583
|
+
soy.$$stripHtmlTags(value.content));
|
282
584
|
}
|
283
|
-
|
284
|
-
|
585
|
+
return soy.esc.$$escapeHtmlNospaceHelper(value);
|
586
|
+
};
|
587
|
+
|
588
|
+
|
589
|
+
/**
|
590
|
+
* Filters out strings that cannot be a substring of a valid HTML attribute.
|
591
|
+
*
|
592
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
593
|
+
* will be coerced to a string.
|
594
|
+
* @return {string} A valid HTML attribute name part or name/value pair.
|
595
|
+
* {@code "zSoyz"} if the input is invalid.
|
596
|
+
*/
|
597
|
+
soy.$$filterHtmlAttribute = function(value) {
|
598
|
+
if (typeof value === 'object' && value &&
|
599
|
+
value.contentKind === soydata.SanitizedContentKind.HTML_ATTRIBUTE) {
|
600
|
+
return value.content.replace(/=([^"']*)$/, '="$1"');
|
285
601
|
}
|
286
|
-
return
|
602
|
+
return soy.esc.$$filterHtmlAttributeHelper(value);
|
287
603
|
};
|
288
604
|
|
605
|
+
|
289
606
|
/**
|
290
|
-
*
|
291
|
-
*
|
292
|
-
* @
|
607
|
+
* Filters out strings that cannot be a substring of a valid HTML element name.
|
608
|
+
*
|
609
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
610
|
+
* will be coerced to a string.
|
611
|
+
* @return {string} A valid HTML element name part.
|
612
|
+
* {@code "zSoyz"} if the input is invalid.
|
613
|
+
*/
|
614
|
+
soy.$$filterHtmlElementName = function(value) {
|
615
|
+
return soy.esc.$$filterHtmlElementNameHelper(value);
|
616
|
+
};
|
617
|
+
|
618
|
+
|
619
|
+
/**
|
620
|
+
* Escapes characters in the value to make it valid content for a JS string
|
621
|
+
* literal.
|
622
|
+
*
|
623
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
624
|
+
* will be coerced to a string.
|
625
|
+
* @return {string} An escaped version of value.
|
626
|
+
* @deprecated
|
293
627
|
*/
|
294
|
-
soy.$$
|
295
|
-
|
296
|
-
AMP: /&/g,
|
297
|
-
LT: /</g,
|
298
|
-
GT: />/g,
|
299
|
-
QUOT: /\"/g
|
628
|
+
soy.$$escapeJs = function(value) {
|
629
|
+
return soy.$$escapeJsString(value);
|
300
630
|
};
|
301
631
|
|
302
632
|
|
303
633
|
/**
|
304
|
-
* Escapes characters in the
|
634
|
+
* Escapes characters in the value to make it valid content for a JS string
|
635
|
+
* literal.
|
305
636
|
*
|
306
|
-
* @param {*}
|
637
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
307
638
|
* will be coerced to a string.
|
308
|
-
* @return {string} An escaped
|
309
|
-
*/
|
310
|
-
soy.$$
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
sb[i] = soy.$$escapeChar(s.charAt(i));
|
639
|
+
* @return {string} An escaped version of value.
|
640
|
+
*/
|
641
|
+
soy.$$escapeJsString = function(value) {
|
642
|
+
if (typeof value === 'object' &&
|
643
|
+
value.contentKind === soydata.SanitizedContentKind.JS_STR_CHARS) {
|
644
|
+
return value.content;
|
315
645
|
}
|
316
|
-
return
|
646
|
+
return soy.esc.$$escapeJsStringHelper(value);
|
317
647
|
};
|
318
648
|
|
319
649
|
|
320
650
|
/**
|
321
|
-
*
|
322
|
-
*
|
323
|
-
* @param {
|
324
|
-
*
|
651
|
+
* Encodes a value as a JavaScript literal.
|
652
|
+
*
|
653
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
654
|
+
* will be coerced to a string.
|
655
|
+
* @return {string} A JavaScript code representation of the input.
|
325
656
|
*/
|
326
|
-
soy.$$
|
327
|
-
|
328
|
-
|
657
|
+
soy.$$escapeJsValue = function(value) {
|
658
|
+
// We surround values with spaces so that they can't be interpolated into
|
659
|
+
// identifiers by accident.
|
660
|
+
// We could use parentheses but those might be interpreted as a function call.
|
661
|
+
if (value == null) { // Intentionally matches undefined.
|
662
|
+
// Java returns null from maps where there is no corresponding key while
|
663
|
+
// JS returns undefined.
|
664
|
+
// We always output null for compatibility with Java which does not have a
|
665
|
+
// distinct undefined value.
|
666
|
+
return ' null ';
|
329
667
|
}
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
// tab is 9 but handled above
|
336
|
-
if (cc < 256) {
|
337
|
-
rv = '\\x';
|
338
|
-
if (cc < 16 || cc > 256) {
|
339
|
-
rv += '0';
|
340
|
-
}
|
341
|
-
} else {
|
342
|
-
rv = '\\u';
|
343
|
-
if (cc < 4096) { // \u1000
|
344
|
-
rv += '0';
|
345
|
-
}
|
346
|
-
}
|
347
|
-
rv += cc.toString(16).toUpperCase();
|
668
|
+
switch (typeof value) {
|
669
|
+
case 'boolean': case 'number':
|
670
|
+
return ' ' + value + ' ';
|
671
|
+
default:
|
672
|
+
return "'" + soy.esc.$$escapeJsStringHelper(String(value)) + "'";
|
348
673
|
}
|
674
|
+
};
|
349
675
|
|
350
|
-
|
676
|
+
|
677
|
+
/**
|
678
|
+
* Escapes characters in the string to make it valid content for a JS regular
|
679
|
+
* expression literal.
|
680
|
+
*
|
681
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
682
|
+
* will be coerced to a string.
|
683
|
+
* @return {string} An escaped version of value.
|
684
|
+
*/
|
685
|
+
soy.$$escapeJsRegex = function(value) {
|
686
|
+
return soy.esc.$$escapeJsRegexHelper(value);
|
351
687
|
};
|
352
688
|
|
689
|
+
|
690
|
+
/**
|
691
|
+
* Takes a character and returns the escaped string for that character. For
|
692
|
+
* example escapeChar(String.fromCharCode(15)) -> "\\x0E".
|
693
|
+
* @param {string} c The character to escape.
|
694
|
+
* @return {string} An escaped string representing {@code c}.
|
695
|
+
*/
|
696
|
+
soy.$$escapeChar = function(c) {
|
697
|
+
if (c in soy.$$escapeCharJs_) {
|
698
|
+
return soy.$$escapeCharJs_[c];
|
699
|
+
}
|
700
|
+
var rv = c;
|
701
|
+
var cc = c.charCodeAt(0);
|
702
|
+
if (cc > 31 && cc < 127) {
|
703
|
+
rv = c;
|
704
|
+
} else {
|
705
|
+
// tab is 9 but handled above
|
706
|
+
if (cc < 256) {
|
707
|
+
rv = '\\x';
|
708
|
+
if (cc < 16 || cc > 256) {
|
709
|
+
rv += '0';
|
710
|
+
}
|
711
|
+
} else {
|
712
|
+
rv = '\\u';
|
713
|
+
if (cc < 4096) { // \u1000
|
714
|
+
rv += '0';
|
715
|
+
}
|
716
|
+
}
|
717
|
+
rv += cc.toString(16).toUpperCase();
|
718
|
+
}
|
719
|
+
|
720
|
+
return soy.$$escapeCharJs_[c] = rv;
|
721
|
+
};
|
722
|
+
|
723
|
+
/**
|
724
|
+
* Character mappings used internally for soy.$$escapeJs
|
725
|
+
* @private
|
726
|
+
* @type {Object}
|
727
|
+
*/
|
728
|
+
soy.$$escapeCharJs_ = {
|
729
|
+
'\b': '\\b',
|
730
|
+
'\f': '\\f',
|
731
|
+
'\n': '\\n',
|
732
|
+
'\r': '\\r',
|
733
|
+
'\t': '\\t',
|
734
|
+
'\x0B': '\\x0B', // '\v' is not supported in JScript
|
735
|
+
'"': '\\"',
|
736
|
+
'\'': '\\\'',
|
737
|
+
'\\': '\\\\'
|
738
|
+
};
|
739
|
+
|
740
|
+
|
353
741
|
/**
|
354
|
-
*
|
742
|
+
* Matches all URI mark characters that conflict with HTML attribute delimiters
|
743
|
+
* or that cannot appear in a CSS uri.
|
744
|
+
* From <a href="http://www.w3.org/TR/CSS2/grammar.html">G.2: CSS grammar</a>
|
745
|
+
* <pre>
|
746
|
+
* url ([!#$%&*-~]|{nonascii}|{escape})*
|
747
|
+
* </pre>
|
748
|
+
*
|
749
|
+
* @type {RegExp}
|
355
750
|
* @private
|
356
|
-
* @type {Object}
|
357
751
|
*/
|
358
|
-
soy.$$
|
359
|
-
'\b': '\\b',
|
360
|
-
'\f': '\\f',
|
361
|
-
'\n': '\\n',
|
362
|
-
'\r': '\\r',
|
363
|
-
'\t': '\\t',
|
364
|
-
'\x0B': '\\x0B', // '\v' is not supported in JScript
|
365
|
-
'"': '\\"',
|
366
|
-
'\'': '\\\'',
|
367
|
-
'\\': '\\\\'
|
368
|
-
};
|
752
|
+
soy.$$problematicUriMarks_ = /['()]/g;
|
369
753
|
|
754
|
+
/**
|
755
|
+
* @param {string} ch A single character in {@link soy.$$problematicUriMarks_}.
|
756
|
+
* @return {string}
|
757
|
+
* @private
|
758
|
+
*/
|
759
|
+
soy.$$pctEncode_ = function(ch) {
|
760
|
+
return '%' + ch.charCodeAt(0).toString(16);
|
761
|
+
};
|
370
762
|
|
371
763
|
/**
|
372
764
|
* Escapes a string so that it can be safely included in a URI.
|
373
765
|
*
|
374
|
-
* @param {*}
|
766
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
767
|
+
* will be coerced to a string.
|
768
|
+
* @return {string} An escaped version of value.
|
769
|
+
*/
|
770
|
+
soy.$$escapeUri = function(value) {
|
771
|
+
if (typeof value === 'object' &&
|
772
|
+
value.contentKind === soydata.SanitizedContentKind.URI) {
|
773
|
+
return soy.$$normalizeUri(value);
|
774
|
+
}
|
775
|
+
// Apostophes and parentheses are not matched by encodeURIComponent.
|
776
|
+
// They are technically special in URIs, but only appear in the obsolete mark
|
777
|
+
// production in Appendix D.2 of RFC 3986, so can be encoded without changing
|
778
|
+
// semantics.
|
779
|
+
var encoded = soy.esc.$$escapeUriHelper(value);
|
780
|
+
soy.$$problematicUriMarks_.lastIndex = 0;
|
781
|
+
if (soy.$$problematicUriMarks_.test(encoded)) {
|
782
|
+
return encoded.replace(soy.$$problematicUriMarks_, soy.$$pctEncode_);
|
783
|
+
}
|
784
|
+
return encoded;
|
785
|
+
};
|
786
|
+
|
787
|
+
|
788
|
+
/**
|
789
|
+
* Removes rough edges from a URI by escaping any raw HTML/JS string delimiters.
|
790
|
+
*
|
791
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
792
|
+
* will be coerced to a string.
|
793
|
+
* @return {string} An escaped version of value.
|
794
|
+
*/
|
795
|
+
soy.$$normalizeUri = function(value) {
|
796
|
+
return soy.esc.$$normalizeUriHelper(value);
|
797
|
+
};
|
798
|
+
|
799
|
+
|
800
|
+
/**
|
801
|
+
* Vets a URI's protocol and removes rough edges from a URI by escaping
|
802
|
+
* any raw HTML/JS string delimiters.
|
803
|
+
*
|
804
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
805
|
+
* will be coerced to a string.
|
806
|
+
* @return {string} An escaped version of value.
|
807
|
+
*/
|
808
|
+
soy.$$filterNormalizeUri = function(value) {
|
809
|
+
return soy.esc.$$filterNormalizeUriHelper(value);
|
810
|
+
};
|
811
|
+
|
812
|
+
|
813
|
+
/**
|
814
|
+
* Escapes a string so it can safely be included inside a quoted CSS string.
|
815
|
+
*
|
816
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
817
|
+
* will be coerced to a string.
|
818
|
+
* @return {string} An escaped version of value.
|
819
|
+
*/
|
820
|
+
soy.$$escapeCssString = function(value) {
|
821
|
+
return soy.esc.$$escapeCssStringHelper(value);
|
822
|
+
};
|
823
|
+
|
824
|
+
|
825
|
+
/**
|
826
|
+
* Encodes a value as a CSS identifier part, keyword, or quantity.
|
827
|
+
*
|
828
|
+
* @param {*} value The value to escape. May not be a string, but the value
|
375
829
|
* will be coerced to a string.
|
376
|
-
* @return {string}
|
377
|
-
*/
|
378
|
-
soy.$$
|
830
|
+
* @return {string} A safe CSS identifier part, keyword, or quanitity.
|
831
|
+
*/
|
832
|
+
soy.$$filterCssValue = function(value) {
|
833
|
+
// Uses == to intentionally match null and undefined for Java compatibility.
|
834
|
+
if (value == null) {
|
835
|
+
return '';
|
836
|
+
}
|
837
|
+
return soy.esc.$$filterCssValueHelper(value);
|
838
|
+
};
|
839
|
+
|
840
|
+
|
841
|
+
// -----------------------------------------------------------------------------
|
842
|
+
// Basic directives/functions.
|
843
|
+
|
844
|
+
|
845
|
+
/**
|
846
|
+
* Converts \r\n, \r, and \n to <br>s
|
847
|
+
* @param {*} str The string in which to convert newlines.
|
848
|
+
* @return {string} A copy of {@code str} with converted newlines.
|
849
|
+
*/
|
850
|
+
soy.$$changeNewlineToBr = function(str) {
|
379
851
|
|
380
852
|
str = String(str);
|
381
853
|
|
382
|
-
//
|
383
|
-
//
|
384
|
-
|
385
|
-
// apps, it saves about 70us per call.
|
386
|
-
if (!soy.$$ENCODE_URI_REGEXP_.test(str)) {
|
387
|
-
return encodeURIComponent(str);
|
388
|
-
} else {
|
854
|
+
// This quick test helps in the case when there are no chars to replace, in
|
855
|
+
// the worst case this makes barely a difference to the time taken.
|
856
|
+
if (!soy.$$CHANGE_NEWLINE_TO_BR_RE_.test(str)) {
|
389
857
|
return str;
|
390
858
|
}
|
859
|
+
|
860
|
+
return str.replace(/(\r\n|\r|\n)/g, '<br>');
|
391
861
|
};
|
392
862
|
|
393
863
|
/**
|
394
|
-
* Regular expression used
|
864
|
+
* Regular expression used within $$changeNewlineToBr().
|
395
865
|
* @type {RegExp}
|
396
866
|
* @private
|
397
867
|
*/
|
398
|
-
soy.$$
|
868
|
+
soy.$$CHANGE_NEWLINE_TO_BR_RE_ = /[\r\n]/;
|
399
869
|
|
400
870
|
|
401
871
|
/**
|
@@ -431,7 +901,7 @@ soy.$$insertWordBreaks = function(str, maxCharsBetweenWordBreaks) {
|
|
431
901
|
charCode != soy.$$CharCode_.SPACE) {
|
432
902
|
resultArr[resultArrLen++] = str.substring(flushIndex, i);
|
433
903
|
flushIndex = i;
|
434
|
-
resultArr[resultArrLen++] = soy
|
904
|
+
resultArr[resultArrLen++] = soy.$$WORD_BREAK_;
|
435
905
|
numCharsWithoutBreak = 0;
|
436
906
|
}
|
437
907
|
|
@@ -496,7 +966,7 @@ soy.$$insertWordBreaks = function(str, maxCharsBetweenWordBreaks) {
|
|
496
966
|
};
|
497
967
|
|
498
968
|
/**
|
499
|
-
* Special characters used within insertWordBreaks().
|
969
|
+
* Special characters used within $$insertWordBreaks().
|
500
970
|
* @enum {number}
|
501
971
|
* @private
|
502
972
|
*/
|
@@ -515,34 +985,103 @@ soy.$$CharCode_ = {
|
|
515
985
|
* @type {string}
|
516
986
|
* @private
|
517
987
|
*/
|
518
|
-
soy
|
519
|
-
soy
|
988
|
+
soy.$$WORD_BREAK_ =
|
989
|
+
soy.$$IS_WEBKIT_ ? '<wbr></wbr>' : soy.$$IS_OPERA_ ? '­' : '<wbr>';
|
520
990
|
|
521
991
|
|
522
992
|
/**
|
523
|
-
*
|
524
|
-
*
|
525
|
-
*
|
993
|
+
* Truncates a string to a given max length (if it's currently longer),
|
994
|
+
* optionally adding ellipsis at the end.
|
995
|
+
*
|
996
|
+
* @param {*} str The string to truncate. Can be other types, but the value will
|
997
|
+
* be coerced to a string.
|
998
|
+
* @param {number} maxLen The maximum length of the string after truncation
|
999
|
+
* (including ellipsis, if applicable).
|
1000
|
+
* @param {boolean} doAddEllipsis Whether to add ellipsis if the string needs
|
1001
|
+
* truncation.
|
1002
|
+
* @return {string} The string after truncation.
|
526
1003
|
*/
|
527
|
-
soy.$$
|
1004
|
+
soy.$$truncate = function(str, maxLen, doAddEllipsis) {
|
528
1005
|
|
529
1006
|
str = String(str);
|
1007
|
+
if (str.length <= maxLen) {
|
1008
|
+
return str; // no need to truncate
|
1009
|
+
}
|
530
1010
|
|
531
|
-
//
|
532
|
-
//
|
533
|
-
if (
|
534
|
-
|
1011
|
+
// If doAddEllipsis, either reduce maxLen to compensate, or else if maxLen is
|
1012
|
+
// too small, just turn off doAddEllipsis.
|
1013
|
+
if (doAddEllipsis) {
|
1014
|
+
if (maxLen > 3) {
|
1015
|
+
maxLen -= 3;
|
1016
|
+
} else {
|
1017
|
+
doAddEllipsis = false;
|
1018
|
+
}
|
535
1019
|
}
|
536
1020
|
|
537
|
-
|
1021
|
+
// Make sure truncating at maxLen doesn't cut up a unicode surrogate pair.
|
1022
|
+
if (soy.$$isHighSurrogate_(str.charAt(maxLen - 1)) &&
|
1023
|
+
soy.$$isLowSurrogate_(str.charAt(maxLen))) {
|
1024
|
+
maxLen -= 1;
|
1025
|
+
}
|
1026
|
+
|
1027
|
+
// Truncate.
|
1028
|
+
str = str.substring(0, maxLen);
|
1029
|
+
|
1030
|
+
// Add ellipsis.
|
1031
|
+
if (doAddEllipsis) {
|
1032
|
+
str += '...';
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
return str;
|
538
1036
|
};
|
539
1037
|
|
540
1038
|
/**
|
541
|
-
*
|
542
|
-
* @
|
1039
|
+
* Private helper for $$truncate() to check whether a char is a high surrogate.
|
1040
|
+
* @param {string} ch The char to check.
|
1041
|
+
* @return {boolean} Whether the given char is a unicode high surrogate.
|
543
1042
|
* @private
|
544
1043
|
*/
|
545
|
-
soy.$$
|
1044
|
+
soy.$$isHighSurrogate_ = function(ch) {
|
1045
|
+
return 0xD800 <= ch && ch <= 0xDBFF;
|
1046
|
+
};
|
1047
|
+
|
1048
|
+
/**
|
1049
|
+
* Private helper for $$truncate() to check whether a char is a low surrogate.
|
1050
|
+
* @param {string} ch The char to check.
|
1051
|
+
* @return {boolean} Whether the given char is a unicode low surrogate.
|
1052
|
+
* @private
|
1053
|
+
*/
|
1054
|
+
soy.$$isLowSurrogate_ = function(ch) {
|
1055
|
+
return 0xDC00 <= ch && ch <= 0xDFFF;
|
1056
|
+
};
|
1057
|
+
|
1058
|
+
|
1059
|
+
// -----------------------------------------------------------------------------
|
1060
|
+
// Bidi directives/functions.
|
1061
|
+
|
1062
|
+
|
1063
|
+
/**
|
1064
|
+
* Returns the leading horizontal edge, i.e. "left" or "right", depending on
|
1065
|
+
* bidiGlobalDir.
|
1066
|
+
* @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
|
1067
|
+
* if rtl, 0 if unknown.
|
1068
|
+
* @return {string} "right" for RTL context and "left" otherwise.
|
1069
|
+
*/
|
1070
|
+
soy.$$bidiStartEdge = function(bidiGlobalDir) {
|
1071
|
+
return bidiGlobalDir < 0 ? 'right' : 'left';
|
1072
|
+
};
|
1073
|
+
|
1074
|
+
|
1075
|
+
/**
|
1076
|
+
* Returns the trailing horizontal edge, i.e. "right" or "left", depending on
|
1077
|
+
* bidiGlobalDir.
|
1078
|
+
* @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
|
1079
|
+
* if rtl, 0 if unknown.
|
1080
|
+
* @return {string} "left" for RTL context and "right" otherwise.
|
1081
|
+
*/
|
1082
|
+
soy.$$bidiEndEdge = function(bidiGlobalDir) {
|
1083
|
+
return bidiGlobalDir < 0 ? 'left' : 'right';
|
1084
|
+
};
|
546
1085
|
|
547
1086
|
|
548
1087
|
/**
|
@@ -579,10 +1118,24 @@ soy.$$bidiTextDir = function(text, opt_isHtml) {
|
|
579
1118
|
*/
|
580
1119
|
soy.$$bidiDirAttr = function(bidiGlobalDir, text, opt_isHtml) {
|
581
1120
|
var dir = soy.$$bidiTextDir(text, opt_isHtml);
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
1121
|
+
return new soydata.SanitizedHtmlAttribute(
|
1122
|
+
dir && dir != bidiGlobalDir ? dir < 0 ? 'dir=rtl' : 'dir=ltr' : '');
|
1123
|
+
};
|
1124
|
+
|
1125
|
+
|
1126
|
+
/**
|
1127
|
+
* Returns a Unicode BiDi mark matching bidiGlobalDir (LRM or RLM), or an empty
|
1128
|
+
* string if bidiGlobalDir is 0 (unknown).
|
1129
|
+
* @param {number} bidiGlobalDir The global directionality context: 1 if ltr, -1
|
1130
|
+
* if rtl, 0 if unknown.
|
1131
|
+
* @return {string} A Unicode bidi mark matching bidiGlobalDir, or the empty
|
1132
|
+
* string when bidiGlobalDir is 0 (unknown).
|
1133
|
+
*/
|
1134
|
+
soy.$$bidiMark = function(bidiGlobalDir) {
|
1135
|
+
return (
|
1136
|
+
(bidiGlobalDir > 0) ? '\u200E' /*LRM*/ :
|
1137
|
+
(bidiGlobalDir < 0) ? '\u200F' /*RLM*/ :
|
1138
|
+
'');
|
586
1139
|
};
|
587
1140
|
|
588
1141
|
|
@@ -597,13 +1150,13 @@ soy.$$bidiDirAttr = function(bidiGlobalDir, text, opt_isHtml) {
|
|
597
1150
|
* @param {string} text The text whose directionality is to be estimated.
|
598
1151
|
* @param {boolean=} opt_isHtml Whether text is HTML/HTML-escaped.
|
599
1152
|
* Default: false.
|
600
|
-
* @return {string} A Unicode bidi mark matching bidiGlobalDir, or
|
601
|
-
*
|
602
|
-
* bidiGlobalDir.
|
1153
|
+
* @return {string} A Unicode bidi mark matching bidiGlobalDir, or the empty
|
1154
|
+
* string when text's overall and exit directionalities both match
|
1155
|
+
* bidiGlobalDir, or bidiGlobalDir is 0 (unknown).
|
603
1156
|
*/
|
604
1157
|
soy.$$bidiMarkAfter = function(bidiGlobalDir, text, opt_isHtml) {
|
605
1158
|
var dir = soy.$$bidiTextDir(text, opt_isHtml);
|
606
|
-
return soy.$$
|
1159
|
+
return soy.$$bidiMarkAfterKnownDir_(bidiGlobalDir, dir, text, opt_isHtml);
|
607
1160
|
};
|
608
1161
|
|
609
1162
|
|
@@ -621,9 +1174,10 @@ soy.$$bidiMarkAfter = function(bidiGlobalDir, text, opt_isHtml) {
|
|
621
1174
|
* Default: false.
|
622
1175
|
* @return {string} A Unicode bidi mark matching bidiGlobalDir, or
|
623
1176
|
* the empty string when text's overall and exit directionalities both match
|
624
|
-
* bidiGlobalDir.
|
1177
|
+
* bidiGlobalDir, or bidiGlobalDir is 0 (unknown).
|
1178
|
+
* @private
|
625
1179
|
*/
|
626
|
-
soy.$$
|
1180
|
+
soy.$$bidiMarkAfterKnownDir_ = function(bidiGlobalDir, dir, text, opt_isHtml) {
|
627
1181
|
return (
|
628
1182
|
bidiGlobalDir > 0 && (dir < 0 ||
|
629
1183
|
soy.$$bidiIsRtlExitText_(text, opt_isHtml)) ? '\u200E' : // LRM
|
@@ -673,7 +1227,7 @@ soy.$$BIDI_HTML_SKIP_RE_ = /<[^>]*>|&[^;]+;/g;
|
|
673
1227
|
soy.$$bidiSpanWrap = function(bidiGlobalDir, str) {
|
674
1228
|
str = String(str);
|
675
1229
|
var textDir = soy.$$bidiTextDir(str, true);
|
676
|
-
var reset = soy.$$
|
1230
|
+
var reset = soy.$$bidiMarkAfterKnownDir_(bidiGlobalDir, textDir, str, true);
|
677
1231
|
if (textDir > 0 && bidiGlobalDir <= 0) {
|
678
1232
|
str = '<span dir=ltr>' + str + '</span>';
|
679
1233
|
} else if (textDir < 0 && bidiGlobalDir >= 0) {
|
@@ -699,7 +1253,7 @@ soy.$$bidiSpanWrap = function(bidiGlobalDir, str) {
|
|
699
1253
|
soy.$$bidiUnicodeWrap = function(bidiGlobalDir, str) {
|
700
1254
|
str = String(str);
|
701
1255
|
var textDir = soy.$$bidiTextDir(str, true);
|
702
|
-
var reset = soy.$$
|
1256
|
+
var reset = soy.$$bidiMarkAfterKnownDir_(bidiGlobalDir, textDir, str, true);
|
703
1257
|
if (textDir > 0 && bidiGlobalDir <= 0) {
|
704
1258
|
str = '\u202A' + str + '\u202C';
|
705
1259
|
} else if (textDir < 0 && bidiGlobalDir >= 0) {
|
@@ -878,3 +1432,481 @@ soy.$$bidiIsRtlExitText_ = function(str, opt_isHtml) {
|
|
878
1432
|
str = soy.$$bidiStripHtmlIfNecessary_(str, opt_isHtml);
|
879
1433
|
return soy.$$bidiRtlExitDirCheckRe_.test(str);
|
880
1434
|
};
|
1435
|
+
|
1436
|
+
|
1437
|
+
// -----------------------------------------------------------------------------
|
1438
|
+
// Generated code.
|
1439
|
+
|
1440
|
+
|
1441
|
+
|
1442
|
+
|
1443
|
+
// START GENERATED CODE FOR ESCAPERS.
|
1444
|
+
|
1445
|
+
/**
|
1446
|
+
* @type {function (*) : string}
|
1447
|
+
*/
|
1448
|
+
soy.esc.$$escapeUriHelper = function(v) {
|
1449
|
+
return encodeURIComponent(String(v));
|
1450
|
+
};
|
1451
|
+
|
1452
|
+
/**
|
1453
|
+
* Maps charcters to the escaped versions for the named escape directives.
|
1454
|
+
* @type {Object.<string, string>}
|
1455
|
+
* @private
|
1456
|
+
*/
|
1457
|
+
soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = {
|
1458
|
+
'\x00': '\x26#0;',
|
1459
|
+
'\x22': '\x26quot;',
|
1460
|
+
'\x26': '\x26amp;',
|
1461
|
+
'\x27': '\x26#39;',
|
1462
|
+
'\x3c': '\x26lt;',
|
1463
|
+
'\x3e': '\x26gt;',
|
1464
|
+
'\x09': '\x26#9;',
|
1465
|
+
'\x0a': '\x26#10;',
|
1466
|
+
'\x0b': '\x26#11;',
|
1467
|
+
'\x0c': '\x26#12;',
|
1468
|
+
'\x0d': '\x26#13;',
|
1469
|
+
' ': '\x26#32;',
|
1470
|
+
'-': '\x26#45;',
|
1471
|
+
'\/': '\x26#47;',
|
1472
|
+
'\x3d': '\x26#61;',
|
1473
|
+
'`': '\x26#96;',
|
1474
|
+
'\x85': '\x26#133;',
|
1475
|
+
'\xa0': '\x26#160;',
|
1476
|
+
'\u2028': '\x26#8232;',
|
1477
|
+
'\u2029': '\x26#8233;'
|
1478
|
+
};
|
1479
|
+
|
1480
|
+
/**
|
1481
|
+
* A function that can be used with String.replace..
|
1482
|
+
* @param {string} ch A single character matched by a compatible matcher.
|
1483
|
+
* @return {string} A token in the output language.
|
1484
|
+
* @private
|
1485
|
+
*/
|
1486
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_ = function(ch) {
|
1487
|
+
return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_[ch];
|
1488
|
+
};
|
1489
|
+
|
1490
|
+
/**
|
1491
|
+
* Maps charcters to the escaped versions for the named escape directives.
|
1492
|
+
* @type {Object.<string, string>}
|
1493
|
+
* @private
|
1494
|
+
*/
|
1495
|
+
soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = {
|
1496
|
+
'\x00': '\\x00',
|
1497
|
+
'\x08': '\\x08',
|
1498
|
+
'\x09': '\\t',
|
1499
|
+
'\x0a': '\\n',
|
1500
|
+
'\x0b': '\\x0b',
|
1501
|
+
'\x0c': '\\f',
|
1502
|
+
'\x0d': '\\r',
|
1503
|
+
'\x22': '\\x22',
|
1504
|
+
'\x26': '\\x26',
|
1505
|
+
'\x27': '\\x27',
|
1506
|
+
'\/': '\\\/',
|
1507
|
+
'\x3c': '\\x3c',
|
1508
|
+
'\x3d': '\\x3d',
|
1509
|
+
'\x3e': '\\x3e',
|
1510
|
+
'\\': '\\\\',
|
1511
|
+
'\x85': '\\x85',
|
1512
|
+
'\u2028': '\\u2028',
|
1513
|
+
'\u2029': '\\u2029',
|
1514
|
+
'$': '\\x24',
|
1515
|
+
'(': '\\x28',
|
1516
|
+
')': '\\x29',
|
1517
|
+
'*': '\\x2a',
|
1518
|
+
'+': '\\x2b',
|
1519
|
+
',': '\\x2c',
|
1520
|
+
'-': '\\x2d',
|
1521
|
+
'.': '\\x2e',
|
1522
|
+
':': '\\x3a',
|
1523
|
+
'?': '\\x3f',
|
1524
|
+
'[': '\\x5b',
|
1525
|
+
']': '\\x5d',
|
1526
|
+
'^': '\\x5e',
|
1527
|
+
'{': '\\x7b',
|
1528
|
+
'|': '\\x7c',
|
1529
|
+
'}': '\\x7d'
|
1530
|
+
};
|
1531
|
+
|
1532
|
+
/**
|
1533
|
+
* A function that can be used with String.replace..
|
1534
|
+
* @param {string} ch A single character matched by a compatible matcher.
|
1535
|
+
* @return {string} A token in the output language.
|
1536
|
+
* @private
|
1537
|
+
*/
|
1538
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_ = function(ch) {
|
1539
|
+
return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_[ch];
|
1540
|
+
};
|
1541
|
+
|
1542
|
+
/**
|
1543
|
+
* Maps charcters to the escaped versions for the named escape directives.
|
1544
|
+
* @type {Object.<string, string>}
|
1545
|
+
* @private
|
1546
|
+
*/
|
1547
|
+
soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_ = {
|
1548
|
+
'\x00': '\\0 ',
|
1549
|
+
'\x08': '\\8 ',
|
1550
|
+
'\x09': '\\9 ',
|
1551
|
+
'\x0a': '\\a ',
|
1552
|
+
'\x0b': '\\b ',
|
1553
|
+
'\x0c': '\\c ',
|
1554
|
+
'\x0d': '\\d ',
|
1555
|
+
'\x22': '\\22 ',
|
1556
|
+
'\x26': '\\26 ',
|
1557
|
+
'\x27': '\\27 ',
|
1558
|
+
'(': '\\28 ',
|
1559
|
+
')': '\\29 ',
|
1560
|
+
'*': '\\2a ',
|
1561
|
+
'\/': '\\2f ',
|
1562
|
+
':': '\\3a ',
|
1563
|
+
';': '\\3b ',
|
1564
|
+
'\x3c': '\\3c ',
|
1565
|
+
'\x3d': '\\3d ',
|
1566
|
+
'\x3e': '\\3e ',
|
1567
|
+
'@': '\\40 ',
|
1568
|
+
'\\': '\\5c ',
|
1569
|
+
'{': '\\7b ',
|
1570
|
+
'}': '\\7d ',
|
1571
|
+
'\x85': '\\85 ',
|
1572
|
+
'\xa0': '\\a0 ',
|
1573
|
+
'\u2028': '\\2028 ',
|
1574
|
+
'\u2029': '\\2029 '
|
1575
|
+
};
|
1576
|
+
|
1577
|
+
/**
|
1578
|
+
* A function that can be used with String.replace..
|
1579
|
+
* @param {string} ch A single character matched by a compatible matcher.
|
1580
|
+
* @return {string} A token in the output language.
|
1581
|
+
* @private
|
1582
|
+
*/
|
1583
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_ = function(ch) {
|
1584
|
+
return soy.esc.$$ESCAPE_MAP_FOR_ESCAPE_CSS_STRING_[ch];
|
1585
|
+
};
|
1586
|
+
|
1587
|
+
/**
|
1588
|
+
* Maps charcters to the escaped versions for the named escape directives.
|
1589
|
+
* @type {Object.<string, string>}
|
1590
|
+
* @private
|
1591
|
+
*/
|
1592
|
+
soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = {
|
1593
|
+
'\x00': '%00',
|
1594
|
+
'\x01': '%01',
|
1595
|
+
'\x02': '%02',
|
1596
|
+
'\x03': '%03',
|
1597
|
+
'\x04': '%04',
|
1598
|
+
'\x05': '%05',
|
1599
|
+
'\x06': '%06',
|
1600
|
+
'\x07': '%07',
|
1601
|
+
'\x08': '%08',
|
1602
|
+
'\x09': '%09',
|
1603
|
+
'\x0a': '%0A',
|
1604
|
+
'\x0b': '%0B',
|
1605
|
+
'\x0c': '%0C',
|
1606
|
+
'\x0d': '%0D',
|
1607
|
+
'\x0e': '%0E',
|
1608
|
+
'\x0f': '%0F',
|
1609
|
+
'\x10': '%10',
|
1610
|
+
'\x11': '%11',
|
1611
|
+
'\x12': '%12',
|
1612
|
+
'\x13': '%13',
|
1613
|
+
'\x14': '%14',
|
1614
|
+
'\x15': '%15',
|
1615
|
+
'\x16': '%16',
|
1616
|
+
'\x17': '%17',
|
1617
|
+
'\x18': '%18',
|
1618
|
+
'\x19': '%19',
|
1619
|
+
'\x1a': '%1A',
|
1620
|
+
'\x1b': '%1B',
|
1621
|
+
'\x1c': '%1C',
|
1622
|
+
'\x1d': '%1D',
|
1623
|
+
'\x1e': '%1E',
|
1624
|
+
'\x1f': '%1F',
|
1625
|
+
' ': '%20',
|
1626
|
+
'\x22': '%22',
|
1627
|
+
'\x27': '%27',
|
1628
|
+
'(': '%28',
|
1629
|
+
')': '%29',
|
1630
|
+
'\x3c': '%3C',
|
1631
|
+
'\x3e': '%3E',
|
1632
|
+
'\\': '%5C',
|
1633
|
+
'{': '%7B',
|
1634
|
+
'}': '%7D',
|
1635
|
+
'\x7f': '%7F',
|
1636
|
+
'\x85': '%C2%85',
|
1637
|
+
'\xa0': '%C2%A0',
|
1638
|
+
'\u2028': '%E2%80%A8',
|
1639
|
+
'\u2029': '%E2%80%A9',
|
1640
|
+
'\uff01': '%EF%BC%81',
|
1641
|
+
'\uff03': '%EF%BC%83',
|
1642
|
+
'\uff04': '%EF%BC%84',
|
1643
|
+
'\uff06': '%EF%BC%86',
|
1644
|
+
'\uff07': '%EF%BC%87',
|
1645
|
+
'\uff08': '%EF%BC%88',
|
1646
|
+
'\uff09': '%EF%BC%89',
|
1647
|
+
'\uff0a': '%EF%BC%8A',
|
1648
|
+
'\uff0b': '%EF%BC%8B',
|
1649
|
+
'\uff0c': '%EF%BC%8C',
|
1650
|
+
'\uff0f': '%EF%BC%8F',
|
1651
|
+
'\uff1a': '%EF%BC%9A',
|
1652
|
+
'\uff1b': '%EF%BC%9B',
|
1653
|
+
'\uff1d': '%EF%BC%9D',
|
1654
|
+
'\uff1f': '%EF%BC%9F',
|
1655
|
+
'\uff20': '%EF%BC%A0',
|
1656
|
+
'\uff3b': '%EF%BC%BB',
|
1657
|
+
'\uff3d': '%EF%BC%BD'
|
1658
|
+
};
|
1659
|
+
|
1660
|
+
/**
|
1661
|
+
* A function that can be used with String.replace..
|
1662
|
+
* @param {string} ch A single character matched by a compatible matcher.
|
1663
|
+
* @return {string} A token in the output language.
|
1664
|
+
* @private
|
1665
|
+
*/
|
1666
|
+
soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_ = function(ch) {
|
1667
|
+
return soy.esc.$$ESCAPE_MAP_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_[ch];
|
1668
|
+
};
|
1669
|
+
|
1670
|
+
/**
|
1671
|
+
* Matches characters that need to be escaped for the named directives.
|
1672
|
+
* @type RegExp
|
1673
|
+
* @private
|
1674
|
+
*/
|
1675
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_HTML_ = /[\x00\x22\x26\x27\x3c\x3e]/g;
|
1676
|
+
|
1677
|
+
/**
|
1678
|
+
* Matches characters that need to be escaped for the named directives.
|
1679
|
+
* @type RegExp
|
1680
|
+
* @private
|
1681
|
+
*/
|
1682
|
+
soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_ = /[\x00\x22\x27\x3c\x3e]/g;
|
1683
|
+
|
1684
|
+
/**
|
1685
|
+
* Matches characters that need to be escaped for the named directives.
|
1686
|
+
* @type RegExp
|
1687
|
+
* @private
|
1688
|
+
*/
|
1689
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x26\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g;
|
1690
|
+
|
1691
|
+
/**
|
1692
|
+
* Matches characters that need to be escaped for the named directives.
|
1693
|
+
* @type RegExp
|
1694
|
+
* @private
|
1695
|
+
*/
|
1696
|
+
soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_ = /[\x00\x09-\x0d \x22\x27\x2d\/\x3c-\x3e`\x85\xa0\u2028\u2029]/g;
|
1697
|
+
|
1698
|
+
/**
|
1699
|
+
* Matches characters that need to be escaped for the named directives.
|
1700
|
+
* @type RegExp
|
1701
|
+
* @private
|
1702
|
+
*/
|
1703
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_ = /[\x00\x08-\x0d\x22\x26\x27\/\x3c-\x3e\\\x85\u2028\u2029]/g;
|
1704
|
+
|
1705
|
+
/**
|
1706
|
+
* Matches characters that need to be escaped for the named directives.
|
1707
|
+
* @type RegExp
|
1708
|
+
* @private
|
1709
|
+
*/
|
1710
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_ = /[\x00\x08-\x0d\x22\x24\x26-\/\x3a\x3c-\x3f\x5b-\x5e\x7b-\x7d\x85\u2028\u2029]/g;
|
1711
|
+
|
1712
|
+
/**
|
1713
|
+
* Matches characters that need to be escaped for the named directives.
|
1714
|
+
* @type RegExp
|
1715
|
+
* @private
|
1716
|
+
*/
|
1717
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_ = /[\x00\x08-\x0d\x22\x26-\x2a\/\x3a-\x3e@\\\x7b\x7d\x85\xa0\u2028\u2029]/g;
|
1718
|
+
|
1719
|
+
/**
|
1720
|
+
* Matches characters that need to be escaped for the named directives.
|
1721
|
+
* @type RegExp
|
1722
|
+
* @private
|
1723
|
+
*/
|
1724
|
+
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;
|
1725
|
+
|
1726
|
+
/**
|
1727
|
+
* A pattern that vets values produced by the named directives.
|
1728
|
+
* @type RegExp
|
1729
|
+
* @private
|
1730
|
+
*/
|
1731
|
+
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;
|
1732
|
+
|
1733
|
+
/**
|
1734
|
+
* A pattern that vets values produced by the named directives.
|
1735
|
+
* @type RegExp
|
1736
|
+
* @private
|
1737
|
+
*/
|
1738
|
+
soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_ = /^(?:(?:https?|mailto):|[^&:\/?#]*(?:[\/?#]|$))/i;
|
1739
|
+
|
1740
|
+
/**
|
1741
|
+
* A pattern that vets values produced by the named directives.
|
1742
|
+
* @type RegExp
|
1743
|
+
* @private
|
1744
|
+
*/
|
1745
|
+
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;
|
1746
|
+
|
1747
|
+
/**
|
1748
|
+
* A pattern that vets values produced by the named directives.
|
1749
|
+
* @type RegExp
|
1750
|
+
* @private
|
1751
|
+
*/
|
1752
|
+
soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_ = /^(?!script|style|title|textarea|xmp|no)[a-z0-9_$:-]*$/i;
|
1753
|
+
|
1754
|
+
/**
|
1755
|
+
* A helper for the Soy directive |escapeHtml
|
1756
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1757
|
+
* @return {string} The escaped text.
|
1758
|
+
*/
|
1759
|
+
soy.esc.$$escapeHtmlHelper = function(value) {
|
1760
|
+
var str = String(value);
|
1761
|
+
return str.replace(
|
1762
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_HTML_,
|
1763
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
|
1764
|
+
};
|
1765
|
+
|
1766
|
+
/**
|
1767
|
+
* A helper for the Soy directive |normalizeHtml
|
1768
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1769
|
+
* @return {string} The escaped text.
|
1770
|
+
*/
|
1771
|
+
soy.esc.$$normalizeHtmlHelper = function(value) {
|
1772
|
+
var str = String(value);
|
1773
|
+
return str.replace(
|
1774
|
+
soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_,
|
1775
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
|
1776
|
+
};
|
1777
|
+
|
1778
|
+
/**
|
1779
|
+
* A helper for the Soy directive |escapeHtmlNospace
|
1780
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1781
|
+
* @return {string} The escaped text.
|
1782
|
+
*/
|
1783
|
+
soy.esc.$$escapeHtmlNospaceHelper = function(value) {
|
1784
|
+
var str = String(value);
|
1785
|
+
return str.replace(
|
1786
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_HTML_NOSPACE_,
|
1787
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
|
1788
|
+
};
|
1789
|
+
|
1790
|
+
/**
|
1791
|
+
* A helper for the Soy directive |normalizeHtmlNospace
|
1792
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1793
|
+
* @return {string} The escaped text.
|
1794
|
+
*/
|
1795
|
+
soy.esc.$$normalizeHtmlNospaceHelper = function(value) {
|
1796
|
+
var str = String(value);
|
1797
|
+
return str.replace(
|
1798
|
+
soy.esc.$$MATCHER_FOR_NORMALIZE_HTML_NOSPACE_,
|
1799
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_HTML__AND__NORMALIZE_HTML__AND__ESCAPE_HTML_NOSPACE__AND__NORMALIZE_HTML_NOSPACE_);
|
1800
|
+
};
|
1801
|
+
|
1802
|
+
/**
|
1803
|
+
* A helper for the Soy directive |escapeJsString
|
1804
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1805
|
+
* @return {string} The escaped text.
|
1806
|
+
*/
|
1807
|
+
soy.esc.$$escapeJsStringHelper = function(value) {
|
1808
|
+
var str = String(value);
|
1809
|
+
return str.replace(
|
1810
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_JS_STRING_,
|
1811
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_);
|
1812
|
+
};
|
1813
|
+
|
1814
|
+
/**
|
1815
|
+
* A helper for the Soy directive |escapeJsRegex
|
1816
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1817
|
+
* @return {string} The escaped text.
|
1818
|
+
*/
|
1819
|
+
soy.esc.$$escapeJsRegexHelper = function(value) {
|
1820
|
+
var str = String(value);
|
1821
|
+
return str.replace(
|
1822
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_JS_REGEX_,
|
1823
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_JS_STRING__AND__ESCAPE_JS_REGEX_);
|
1824
|
+
};
|
1825
|
+
|
1826
|
+
/**
|
1827
|
+
* A helper for the Soy directive |escapeCssString
|
1828
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1829
|
+
* @return {string} The escaped text.
|
1830
|
+
*/
|
1831
|
+
soy.esc.$$escapeCssStringHelper = function(value) {
|
1832
|
+
var str = String(value);
|
1833
|
+
return str.replace(
|
1834
|
+
soy.esc.$$MATCHER_FOR_ESCAPE_CSS_STRING_,
|
1835
|
+
soy.esc.$$REPLACER_FOR_ESCAPE_CSS_STRING_);
|
1836
|
+
};
|
1837
|
+
|
1838
|
+
/**
|
1839
|
+
* A helper for the Soy directive |filterCssValue
|
1840
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1841
|
+
* @return {string} The escaped text.
|
1842
|
+
*/
|
1843
|
+
soy.esc.$$filterCssValueHelper = function(value) {
|
1844
|
+
var str = String(value);
|
1845
|
+
if (!soy.esc.$$FILTER_FOR_FILTER_CSS_VALUE_.test(str)) {
|
1846
|
+
return 'zSoyz';
|
1847
|
+
}
|
1848
|
+
return str;
|
1849
|
+
};
|
1850
|
+
|
1851
|
+
/**
|
1852
|
+
* A helper for the Soy directive |normalizeUri
|
1853
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1854
|
+
* @return {string} The escaped text.
|
1855
|
+
*/
|
1856
|
+
soy.esc.$$normalizeUriHelper = function(value) {
|
1857
|
+
var str = String(value);
|
1858
|
+
return str.replace(
|
1859
|
+
soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_,
|
1860
|
+
soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_);
|
1861
|
+
};
|
1862
|
+
|
1863
|
+
/**
|
1864
|
+
* A helper for the Soy directive |filterNormalizeUri
|
1865
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1866
|
+
* @return {string} The escaped text.
|
1867
|
+
*/
|
1868
|
+
soy.esc.$$filterNormalizeUriHelper = function(value) {
|
1869
|
+
var str = String(value);
|
1870
|
+
if (!soy.esc.$$FILTER_FOR_FILTER_NORMALIZE_URI_.test(str)) {
|
1871
|
+
return 'zSoyz';
|
1872
|
+
}
|
1873
|
+
return str.replace(
|
1874
|
+
soy.esc.$$MATCHER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_,
|
1875
|
+
soy.esc.$$REPLACER_FOR_NORMALIZE_URI__AND__FILTER_NORMALIZE_URI_);
|
1876
|
+
};
|
1877
|
+
|
1878
|
+
/**
|
1879
|
+
* A helper for the Soy directive |filterHtmlAttribute
|
1880
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1881
|
+
* @return {string} The escaped text.
|
1882
|
+
*/
|
1883
|
+
soy.esc.$$filterHtmlAttributeHelper = function(value) {
|
1884
|
+
var str = String(value);
|
1885
|
+
if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ATTRIBUTE_.test(str)) {
|
1886
|
+
return 'zSoyz';
|
1887
|
+
}
|
1888
|
+
return str;
|
1889
|
+
};
|
1890
|
+
|
1891
|
+
/**
|
1892
|
+
* A helper for the Soy directive |filterHtmlElementName
|
1893
|
+
* @param {*} value Can be of any type but will be coerced to a string.
|
1894
|
+
* @return {string} The escaped text.
|
1895
|
+
*/
|
1896
|
+
soy.esc.$$filterHtmlElementNameHelper = function(value) {
|
1897
|
+
var str = String(value);
|
1898
|
+
if (!soy.esc.$$FILTER_FOR_FILTER_HTML_ELEMENT_NAME_.test(str)) {
|
1899
|
+
return 'zSoyz';
|
1900
|
+
}
|
1901
|
+
return str;
|
1902
|
+
};
|
1903
|
+
|
1904
|
+
/**
|
1905
|
+
* Matches all tags, HTML comments, and DOCTYPEs in tag soup HTML.
|
1906
|
+
*
|
1907
|
+
* @type {RegExp}
|
1908
|
+
* @private
|
1909
|
+
*/
|
1910
|
+
soy.esc.$$HTML_TAG_REGEX_ = /<(?:!|\/?[a-zA-Z])(?:[^>'"]|"[^"]*"|'[^']*')*>/g;
|
1911
|
+
|
1912
|
+
// END GENERATED CODE
|