mustache-js-rails 4.1.0.2 → 4.1.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f3702b1d6ab853adde07ba099600be7086d949ea394e8edf88907ddb90ce79b9
4
- data.tar.gz: 0f3585fb8621e4e2dfc6718578b3476c5bc3c9ba9c3caf4285872595ea38c948
3
+ metadata.gz: ba03b972d4af990c40401f999c98ada8d943aad34b25fc7ed9736af9238df952
4
+ data.tar.gz: 27606c38fd81ed7e6059a4af887715676b828ef4726031f59879ea15e3238536
5
5
  SHA512:
6
- metadata.gz: a7aa1fcc8ac275d58898f4fa1eaa2dde12aabc3d3866a9ae6b482cfa57739361dfc764ff61dc4134e26774b709b307832ecc539c3e22592eb5edfc9cd91c4a69
7
- data.tar.gz: 225da1502751533c1b99879b1f37db287a787d49185303cdc2305eee8ba2ab5db7f038140a9dfbd56b8647362bbce1bdc7d3cfff4ed83c2f69852c71e41cc814
6
+ metadata.gz: 0d1fc84d6c62768172b881b5911b5316eeed422f853a19cacc6cec1384f29eec37b0ec68887555832d92159e7f8550a7f27b7ee4ea05fe29ef884b074925d1cc
7
+ data.tar.gz: 78d80abe66a54f49e999fd74f7f3ea4a206baaf5afeadba62471fcddd15302f991e45db9299dbd377cad21e7b76f751c3ba79583fd7f4804bbb0f722d34708f9
data/README.md CHANGED
@@ -9,7 +9,7 @@ and [mustache jQuery integration](https://github.com/jonnyreeves/jquery-Mustache
9
9
 
10
10
  Integrated versions are:
11
11
 
12
- * mustache.js - <b id="mustache-js-version">4.2.0</b>
12
+ * mustache.js - <b id="mustache-js-version">4.1.0</b>
13
13
  * jQuery mustache - <b id="jquery-mustache-js-version">0.2.8</b>
14
14
 
15
15
  ### Installation
@@ -1,3 +1,3 @@
1
1
  module MustacheJsRails
2
- VERSION = "4.1.0.2"
2
+ VERSION = "4.1.0.3"
3
3
  end
@@ -1,6 +1,6 @@
1
- /*! jQuery Mustache - v0.2.8 - 2013-06-23
1
+ /*! jQuery Mustache - v0.2.8 - 2021-06-14
2
2
  * https://github.com/jonnyreeves/jquery-Mustache
3
- * Copyright (c) 2013 Jonny Reeves; Licensed MIT */
3
+ * Copyright (c) 2021 Jonny Reeves; Licensed MIT */
4
4
 
5
5
  /*global jQuery, window */
6
6
  (function ($, window) {
@@ -64,8 +64,8 @@
64
64
  * Adds one or more tempaltes from the DOM using either the supplied templateElementIds or by retrieving all script
65
65
  * tags of the 'domTemplateType'. Templates added in this fashion will be registered with their elementId value.
66
66
  *
67
- * @param [...templateElementIds] List of element id's present on the DOM which contain templates to be added;
68
- * if none are supplied all script tags that are of the same type as the
67
+ * @param [...templateElementIds] List of element id's present on the DOM which contain templates to be added;
68
+ * if none are supplied all script tags that are of the same type as the
69
69
  * `options.domTemplateType` configuration value will be added.
70
70
  */
71
71
  function addFromDom() {
@@ -124,7 +124,7 @@
124
124
  }
125
125
  return '';
126
126
  }
127
- return getMustache().to_html(templateMap[templateName], templateData, templateMap);
127
+ return getMustache().render(templateMap[templateName], templateData, templateMap);
128
128
  }
129
129
 
130
130
  /**
@@ -1,764 +1,773 @@
1
- /*!
2
- * mustache.js - Logic-less {{mustache}} templates with JavaScript
3
- * http://github.com/janl/mustache.js
4
- */
5
-
6
- var objectToString = Object.prototype.toString;
7
- var isArray = Array.isArray || function isArrayPolyfill (object) {
8
- return objectToString.call(object) === '[object Array]';
9
- };
10
-
11
- function isFunction (object) {
12
- return typeof object === 'function';
13
- }
14
-
15
- /**
16
- * More correct typeof string handling array
17
- * which normally returns typeof 'object'
18
- */
19
- function typeStr (obj) {
20
- return isArray(obj) ? 'array' : typeof obj;
21
- }
22
-
23
- function escapeRegExp (string) {
24
- return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
25
- }
26
-
27
- /**
28
- * Null safe way of checking whether or not an object,
29
- * including its prototype, has a given property
30
- */
31
- function hasProperty (obj, propName) {
32
- return obj != null && typeof obj === 'object' && (propName in obj);
33
- }
34
-
35
- /**
36
- * Safe way of detecting whether or not the given thing is a primitive and
37
- * whether it has the given property
38
- */
39
- function primitiveHasOwnProperty (primitive, propName) {
40
- return (
41
- primitive != null
42
- && typeof primitive !== 'object'
43
- && primitive.hasOwnProperty
44
- && primitive.hasOwnProperty(propName)
45
- );
46
- }
47
-
48
- // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
49
- // See https://github.com/janl/mustache.js/issues/189
50
- var regExpTest = RegExp.prototype.test;
51
- function testRegExp (re, string) {
52
- return regExpTest.call(re, string);
53
- }
54
-
55
- var nonSpaceRe = /\S/;
56
- function isWhitespace (string) {
57
- return !testRegExp(nonSpaceRe, string);
58
- }
59
-
60
- var entityMap = {
61
- '&': '&amp;',
62
- '<': '&lt;',
63
- '>': '&gt;',
64
- '"': '&quot;',
65
- "'": '&#39;',
66
- '/': '&#x2F;',
67
- '`': '&#x60;',
68
- '=': '&#x3D;'
69
- };
70
-
71
- function escapeHtml (string) {
72
- return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
73
- return entityMap[s];
74
- });
75
- }
76
-
77
- var whiteRe = /\s*/;
78
- var spaceRe = /\s+/;
79
- var equalsRe = /\s*=/;
80
- var curlyRe = /\s*\}/;
81
- var tagRe = /#|\^|\/|>|\{|&|=|!/;
82
-
83
- /**
84
- * Breaks up the given `template` string into a tree of tokens. If the `tags`
85
- * argument is given here it must be an array with two string values: the
86
- * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
87
- * course, the default is to use mustaches (i.e. mustache.tags).
88
- *
89
- * A token is an array with at least 4 elements. The first element is the
90
- * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
91
- * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
92
- * all text that appears outside a symbol this element is "text".
93
- *
94
- * The second element of a token is its "value". For mustache tags this is
95
- * whatever else was inside the tag besides the opening symbol. For text tokens
96
- * this is the text itself.
97
- *
98
- * The third and fourth elements of the token are the start and end indices,
99
- * respectively, of the token in the original template.
100
- *
101
- * Tokens that are the root node of a subtree contain two more elements: 1) an
102
- * array of tokens in the subtree and 2) the index in the original template at
103
- * which the closing tag for that section begins.
104
- *
105
- * Tokens for partials also contain two more elements: 1) a string value of
106
- * indendation prior to that tag and 2) the index of that tag on that line -
107
- * eg a value of 2 indicates the partial is the third tag on this line.
108
- */
109
- function parseTemplate (template, tags) {
110
- if (!template)
111
- return [];
112
- var lineHasNonSpace = false;
113
- var sections = []; // Stack to hold section tokens
114
- var tokens = []; // Buffer to hold the tokens
115
- var spaces = []; // Indices of whitespace tokens on the current line
116
- var hasTag = false; // Is there a {{tag}} on the current line?
117
- var nonSpace = false; // Is there a non-space char on the current line?
118
- var indentation = ''; // Tracks indentation for tags that use it
119
- var tagIndex = 0; // Stores a count of number of tags encountered on a line
120
-
121
- // Strips all whitespace tokens array for the current line
122
- // if there was a {{#tag}} on it and otherwise only space.
123
- function stripSpace () {
124
- if (hasTag && !nonSpace) {
125
- while (spaces.length)
126
- delete tokens[spaces.pop()];
127
- } else {
128
- spaces = [];
129
- }
1
+ // This file has been generated from mustache.mjs
2
+ (function (global, factory) {
3
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
4
+ typeof define === 'function' && define.amd ? define(factory) :
5
+ (global = global || self, global.Mustache = factory());
6
+ }(this, (function () { 'use strict';
7
+
8
+ /*!
9
+ * mustache.js - Logic-less {{mustache}} templates with JavaScript
10
+ * http://github.com/janl/mustache.js
11
+ */
130
12
 
131
- hasTag = false;
132
- nonSpace = false;
133
- }
13
+ var objectToString = Object.prototype.toString;
14
+ var isArray = Array.isArray || function isArrayPolyfill (object) {
15
+ return objectToString.call(object) === '[object Array]';
16
+ };
134
17
 
135
- var openingTagRe, closingTagRe, closingCurlyRe;
136
- function compileTags (tagsToCompile) {
137
- if (typeof tagsToCompile === 'string')
138
- tagsToCompile = tagsToCompile.split(spaceRe, 2);
18
+ function isFunction (object) {
19
+ return typeof object === 'function';
20
+ }
139
21
 
140
- if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)
141
- throw new Error('Invalid tags: ' + tagsToCompile);
22
+ /**
23
+ * More correct typeof string handling array
24
+ * which normally returns typeof 'object'
25
+ */
26
+ function typeStr (obj) {
27
+ return isArray(obj) ? 'array' : typeof obj;
28
+ }
142
29
 
143
- openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*');
144
- closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1]));
145
- closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1]));
30
+ function escapeRegExp (string) {
31
+ return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
146
32
  }
147
33
 
148
- compileTags(tags || mustache.tags);
34
+ /**
35
+ * Null safe way of checking whether or not an object,
36
+ * including its prototype, has a given property
37
+ */
38
+ function hasProperty (obj, propName) {
39
+ return obj != null && typeof obj === 'object' && (propName in obj);
40
+ }
149
41
 
150
- var scanner = new Scanner(template);
42
+ /**
43
+ * Safe way of detecting whether or not the given thing is a primitive and
44
+ * whether it has the given property
45
+ */
46
+ function primitiveHasOwnProperty (primitive, propName) {
47
+ return (
48
+ primitive != null
49
+ && typeof primitive !== 'object'
50
+ && primitive.hasOwnProperty
51
+ && primitive.hasOwnProperty(propName)
52
+ );
53
+ }
151
54
 
152
- var start, type, value, chr, token, openSection;
153
- while (!scanner.eos()) {
154
- start = scanner.pos;
55
+ // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
56
+ // See https://github.com/janl/mustache.js/issues/189
57
+ var regExpTest = RegExp.prototype.test;
58
+ function testRegExp (re, string) {
59
+ return regExpTest.call(re, string);
60
+ }
155
61
 
156
- // Match any text between tags.
157
- value = scanner.scanUntil(openingTagRe);
62
+ var nonSpaceRe = /\S/;
63
+ function isWhitespace (string) {
64
+ return !testRegExp(nonSpaceRe, string);
65
+ }
158
66
 
159
- if (value) {
160
- for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
161
- chr = value.charAt(i);
67
+ var entityMap = {
68
+ '&': '&amp;',
69
+ '<': '&lt;',
70
+ '>': '&gt;',
71
+ '"': '&quot;',
72
+ "'": '&#39;',
73
+ '/': '&#x2F;',
74
+ '`': '&#x60;',
75
+ '=': '&#x3D;'
76
+ };
162
77
 
163
- if (isWhitespace(chr)) {
164
- spaces.push(tokens.length);
165
- indentation += chr;
166
- } else {
167
- nonSpace = true;
168
- lineHasNonSpace = true;
169
- indentation += ' ';
170
- }
78
+ function escapeHtml (string) {
79
+ return String(string).replace(/[&<>"'`=\/]/g, function fromEntityMap (s) {
80
+ return entityMap[s];
81
+ });
82
+ }
171
83
 
172
- tokens.push([ 'text', chr, start, start + 1 ]);
173
- start += 1;
84
+ var whiteRe = /\s*/;
85
+ var spaceRe = /\s+/;
86
+ var equalsRe = /\s*=/;
87
+ var curlyRe = /\s*\}/;
88
+ var tagRe = /#|\^|\/|>|\{|&|=|!/;
174
89
 
175
- // Check for whitespace on the current line.
176
- if (chr === '\n') {
177
- stripSpace();
178
- indentation = '';
179
- tagIndex = 0;
180
- lineHasNonSpace = false;
181
- }
90
+ /**
91
+ * Breaks up the given `template` string into a tree of tokens. If the `tags`
92
+ * argument is given here it must be an array with two string values: the
93
+ * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
94
+ * course, the default is to use mustaches (i.e. mustache.tags).
95
+ *
96
+ * A token is an array with at least 4 elements. The first element is the
97
+ * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
98
+ * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
99
+ * all text that appears outside a symbol this element is "text".
100
+ *
101
+ * The second element of a token is its "value". For mustache tags this is
102
+ * whatever else was inside the tag besides the opening symbol. For text tokens
103
+ * this is the text itself.
104
+ *
105
+ * The third and fourth elements of the token are the start and end indices,
106
+ * respectively, of the token in the original template.
107
+ *
108
+ * Tokens that are the root node of a subtree contain two more elements: 1) an
109
+ * array of tokens in the subtree and 2) the index in the original template at
110
+ * which the closing tag for that section begins.
111
+ *
112
+ * Tokens for partials also contain two more elements: 1) a string value of
113
+ * indendation prior to that tag and 2) the index of that tag on that line -
114
+ * eg a value of 2 indicates the partial is the third tag on this line.
115
+ */
116
+ function parseTemplate (template, tags) {
117
+ if (!template)
118
+ return [];
119
+ var lineHasNonSpace = false;
120
+ var sections = []; // Stack to hold section tokens
121
+ var tokens = []; // Buffer to hold the tokens
122
+ var spaces = []; // Indices of whitespace tokens on the current line
123
+ var hasTag = false; // Is there a {{tag}} on the current line?
124
+ var nonSpace = false; // Is there a non-space char on the current line?
125
+ var indentation = ''; // Tracks indentation for tags that use it
126
+ var tagIndex = 0; // Stores a count of number of tags encountered on a line
127
+
128
+ // Strips all whitespace tokens array for the current line
129
+ // if there was a {{#tag}} on it and otherwise only space.
130
+ function stripSpace () {
131
+ if (hasTag && !nonSpace) {
132
+ while (spaces.length)
133
+ delete tokens[spaces.pop()];
134
+ } else {
135
+ spaces = [];
182
136
  }
183
- }
184
137
 
185
- // Match the opening tag.
186
- if (!scanner.scan(openingTagRe))
187
- break;
188
-
189
- hasTag = true;
190
-
191
- // Get the tag type.
192
- type = scanner.scan(tagRe) || 'name';
193
- scanner.scan(whiteRe);
194
-
195
- // Get the tag value.
196
- if (type === '=') {
197
- value = scanner.scanUntil(equalsRe);
198
- scanner.scan(equalsRe);
199
- scanner.scanUntil(closingTagRe);
200
- } else if (type === '{') {
201
- value = scanner.scanUntil(closingCurlyRe);
202
- scanner.scan(curlyRe);
203
- scanner.scanUntil(closingTagRe);
204
- type = '&';
205
- } else {
206
- value = scanner.scanUntil(closingTagRe);
138
+ hasTag = false;
139
+ nonSpace = false;
207
140
  }
208
141
 
209
- // Match the closing tag.
210
- if (!scanner.scan(closingTagRe))
211
- throw new Error('Unclosed tag at ' + scanner.pos);
142
+ var openingTagRe, closingTagRe, closingCurlyRe;
143
+ function compileTags (tagsToCompile) {
144
+ if (typeof tagsToCompile === 'string')
145
+ tagsToCompile = tagsToCompile.split(spaceRe, 2);
212
146
 
213
- if (type == '>') {
214
- token = [ type, value, start, scanner.pos, indentation, tagIndex, lineHasNonSpace ];
215
- } else {
216
- token = [ type, value, start, scanner.pos ];
217
- }
218
- tagIndex++;
219
- tokens.push(token);
220
-
221
- if (type === '#' || type === '^') {
222
- sections.push(token);
223
- } else if (type === '/') {
224
- // Check section nesting.
225
- openSection = sections.pop();
226
-
227
- if (!openSection)
228
- throw new Error('Unopened section "' + value + '" at ' + start);
229
-
230
- if (openSection[1] !== value)
231
- throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
232
- } else if (type === 'name' || type === '{' || type === '&') {
233
- nonSpace = true;
234
- } else if (type === '=') {
235
- // Set the tags for the next time around.
236
- compileTags(value);
147
+ if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)
148
+ throw new Error('Invalid tags: ' + tagsToCompile);
149
+
150
+ openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\s*');
151
+ closingTagRe = new RegExp('\\s*' + escapeRegExp(tagsToCompile[1]));
152
+ closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tagsToCompile[1]));
237
153
  }
238
- }
239
154
 
240
- stripSpace();
155
+ compileTags(tags || mustache.tags);
156
+
157
+ var scanner = new Scanner(template);
158
+
159
+ var start, type, value, chr, token, openSection;
160
+ while (!scanner.eos()) {
161
+ start = scanner.pos;
241
162
 
242
- // Make sure there are no open sections when we're done.
243
- openSection = sections.pop();
163
+ // Match any text between tags.
164
+ value = scanner.scanUntil(openingTagRe);
244
165
 
245
- if (openSection)
246
- throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
166
+ if (value) {
167
+ for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
168
+ chr = value.charAt(i);
247
169
 
248
- return nestTokens(squashTokens(tokens));
249
- }
170
+ if (isWhitespace(chr)) {
171
+ spaces.push(tokens.length);
172
+ indentation += chr;
173
+ } else {
174
+ nonSpace = true;
175
+ lineHasNonSpace = true;
176
+ indentation += ' ';
177
+ }
250
178
 
251
- /**
252
- * Combines the values of consecutive text tokens in the given `tokens` array
253
- * to a single token.
254
- */
255
- function squashTokens (tokens) {
256
- var squashedTokens = [];
179
+ tokens.push([ 'text', chr, start, start + 1 ]);
180
+ start += 1;
257
181
 
258
- var token, lastToken;
259
- for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
260
- token = tokens[i];
182
+ // Check for whitespace on the current line.
183
+ if (chr === '\n') {
184
+ stripSpace();
185
+ indentation = '';
186
+ tagIndex = 0;
187
+ lineHasNonSpace = false;
188
+ }
189
+ }
190
+ }
261
191
 
262
- if (token) {
263
- if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
264
- lastToken[1] += token[1];
265
- lastToken[3] = token[3];
192
+ // Match the opening tag.
193
+ if (!scanner.scan(openingTagRe))
194
+ break;
195
+
196
+ hasTag = true;
197
+
198
+ // Get the tag type.
199
+ type = scanner.scan(tagRe) || 'name';
200
+ scanner.scan(whiteRe);
201
+
202
+ // Get the tag value.
203
+ if (type === '=') {
204
+ value = scanner.scanUntil(equalsRe);
205
+ scanner.scan(equalsRe);
206
+ scanner.scanUntil(closingTagRe);
207
+ } else if (type === '{') {
208
+ value = scanner.scanUntil(closingCurlyRe);
209
+ scanner.scan(curlyRe);
210
+ scanner.scanUntil(closingTagRe);
211
+ type = '&';
212
+ } else {
213
+ value = scanner.scanUntil(closingTagRe);
214
+ }
215
+
216
+ // Match the closing tag.
217
+ if (!scanner.scan(closingTagRe))
218
+ throw new Error('Unclosed tag at ' + scanner.pos);
219
+
220
+ if (type == '>') {
221
+ token = [ type, value, start, scanner.pos, indentation, tagIndex, lineHasNonSpace ];
266
222
  } else {
267
- squashedTokens.push(token);
268
- lastToken = token;
223
+ token = [ type, value, start, scanner.pos ];
224
+ }
225
+ tagIndex++;
226
+ tokens.push(token);
227
+
228
+ if (type === '#' || type === '^') {
229
+ sections.push(token);
230
+ } else if (type === '/') {
231
+ // Check section nesting.
232
+ openSection = sections.pop();
233
+
234
+ if (!openSection)
235
+ throw new Error('Unopened section "' + value + '" at ' + start);
236
+
237
+ if (openSection[1] !== value)
238
+ throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
239
+ } else if (type === 'name' || type === '{' || type === '&') {
240
+ nonSpace = true;
241
+ } else if (type === '=') {
242
+ // Set the tags for the next time around.
243
+ compileTags(value);
244
+ }
245
+ }
246
+
247
+ stripSpace();
248
+
249
+ // Make sure there are no open sections when we're done.
250
+ openSection = sections.pop();
251
+
252
+ if (openSection)
253
+ throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
254
+
255
+ return nestTokens(squashTokens(tokens));
256
+ }
257
+
258
+ /**
259
+ * Combines the values of consecutive text tokens in the given `tokens` array
260
+ * to a single token.
261
+ */
262
+ function squashTokens (tokens) {
263
+ var squashedTokens = [];
264
+
265
+ var token, lastToken;
266
+ for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
267
+ token = tokens[i];
268
+
269
+ if (token) {
270
+ if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
271
+ lastToken[1] += token[1];
272
+ lastToken[3] = token[3];
273
+ } else {
274
+ squashedTokens.push(token);
275
+ lastToken = token;
276
+ }
277
+ }
278
+ }
279
+
280
+ return squashedTokens;
281
+ }
282
+
283
+ /**
284
+ * Forms the given array of `tokens` into a nested tree structure where
285
+ * tokens that represent a section have two additional items: 1) an array of
286
+ * all tokens that appear in that section and 2) the index in the original
287
+ * template that represents the end of that section.
288
+ */
289
+ function nestTokens (tokens) {
290
+ var nestedTokens = [];
291
+ var collector = nestedTokens;
292
+ var sections = [];
293
+
294
+ var token, section;
295
+ for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
296
+ token = tokens[i];
297
+
298
+ switch (token[0]) {
299
+ case '#':
300
+ case '^':
301
+ collector.push(token);
302
+ sections.push(token);
303
+ collector = token[4] = [];
304
+ break;
305
+ case '/':
306
+ section = sections.pop();
307
+ section[5] = token[2];
308
+ collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
309
+ break;
310
+ default:
311
+ collector.push(token);
269
312
  }
270
313
  }
314
+
315
+ return nestedTokens;
271
316
  }
272
317
 
273
- return squashedTokens;
274
- }
275
-
276
- /**
277
- * Forms the given array of `tokens` into a nested tree structure where
278
- * tokens that represent a section have two additional items: 1) an array of
279
- * all tokens that appear in that section and 2) the index in the original
280
- * template that represents the end of that section.
281
- */
282
- function nestTokens (tokens) {
283
- var nestedTokens = [];
284
- var collector = nestedTokens;
285
- var sections = [];
286
-
287
- var token, section;
288
- for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
289
- token = tokens[i];
290
-
291
- switch (token[0]) {
292
- case '#':
293
- case '^':
294
- collector.push(token);
295
- sections.push(token);
296
- collector = token[4] = [];
318
+ /**
319
+ * A simple string scanner that is used by the template parser to find
320
+ * tokens in template strings.
321
+ */
322
+ function Scanner (string) {
323
+ this.string = string;
324
+ this.tail = string;
325
+ this.pos = 0;
326
+ }
327
+
328
+ /**
329
+ * Returns `true` if the tail is empty (end of string).
330
+ */
331
+ Scanner.prototype.eos = function eos () {
332
+ return this.tail === '';
333
+ };
334
+
335
+ /**
336
+ * Tries to match the given regular expression at the current position.
337
+ * Returns the matched text if it can match, the empty string otherwise.
338
+ */
339
+ Scanner.prototype.scan = function scan (re) {
340
+ var match = this.tail.match(re);
341
+
342
+ if (!match || match.index !== 0)
343
+ return '';
344
+
345
+ var string = match[0];
346
+
347
+ this.tail = this.tail.substring(string.length);
348
+ this.pos += string.length;
349
+
350
+ return string;
351
+ };
352
+
353
+ /**
354
+ * Skips all text until the given regular expression can be matched. Returns
355
+ * the skipped string, which is the entire tail if no match can be made.
356
+ */
357
+ Scanner.prototype.scanUntil = function scanUntil (re) {
358
+ var index = this.tail.search(re), match;
359
+
360
+ switch (index) {
361
+ case -1:
362
+ match = this.tail;
363
+ this.tail = '';
297
364
  break;
298
- case '/':
299
- section = sections.pop();
300
- section[5] = token[2];
301
- collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
365
+ case 0:
366
+ match = '';
302
367
  break;
303
368
  default:
304
- collector.push(token);
369
+ match = this.tail.substring(0, index);
370
+ this.tail = this.tail.substring(index);
305
371
  }
306
- }
307
372
 
308
- return nestedTokens;
309
- }
310
-
311
- /**
312
- * A simple string scanner that is used by the template parser to find
313
- * tokens in template strings.
314
- */
315
- function Scanner (string) {
316
- this.string = string;
317
- this.tail = string;
318
- this.pos = 0;
319
- }
320
-
321
- /**
322
- * Returns `true` if the tail is empty (end of string).
323
- */
324
- Scanner.prototype.eos = function eos () {
325
- return this.tail === '';
326
- };
327
-
328
- /**
329
- * Tries to match the given regular expression at the current position.
330
- * Returns the matched text if it can match, the empty string otherwise.
331
- */
332
- Scanner.prototype.scan = function scan (re) {
333
- var match = this.tail.match(re);
334
-
335
- if (!match || match.index !== 0)
336
- return '';
337
-
338
- var string = match[0];
339
-
340
- this.tail = this.tail.substring(string.length);
341
- this.pos += string.length;
342
-
343
- return string;
344
- };
345
-
346
- /**
347
- * Skips all text until the given regular expression can be matched. Returns
348
- * the skipped string, which is the entire tail if no match can be made.
349
- */
350
- Scanner.prototype.scanUntil = function scanUntil (re) {
351
- var index = this.tail.search(re), match;
352
-
353
- switch (index) {
354
- case -1:
355
- match = this.tail;
356
- this.tail = '';
357
- break;
358
- case 0:
359
- match = '';
360
- break;
361
- default:
362
- match = this.tail.substring(0, index);
363
- this.tail = this.tail.substring(index);
373
+ this.pos += match.length;
374
+
375
+ return match;
376
+ };
377
+
378
+ /**
379
+ * Represents a rendering context by wrapping a view object and
380
+ * maintaining a reference to the parent context.
381
+ */
382
+ function Context (view, parentContext) {
383
+ this.view = view;
384
+ this.cache = { '.': this.view };
385
+ this.parent = parentContext;
364
386
  }
365
387
 
366
- this.pos += match.length;
367
-
368
- return match;
369
- };
370
-
371
- /**
372
- * Represents a rendering context by wrapping a view object and
373
- * maintaining a reference to the parent context.
374
- */
375
- function Context (view, parentContext) {
376
- this.view = view;
377
- this.cache = { '.': this.view };
378
- this.parent = parentContext;
379
- }
380
-
381
- /**
382
- * Creates a new context using the given view with this context
383
- * as the parent.
384
- */
385
- Context.prototype.push = function push (view) {
386
- return new Context(view, this);
387
- };
388
-
389
- /**
390
- * Returns the value of the given name in this context, traversing
391
- * up the context hierarchy if the value is absent in this context's view.
392
- */
393
- Context.prototype.lookup = function lookup (name) {
394
- var cache = this.cache;
395
-
396
- var value;
397
- if (cache.hasOwnProperty(name)) {
398
- value = cache[name];
399
- } else {
400
- var context = this, intermediateValue, names, index, lookupHit = false;
401
-
402
- while (context) {
403
- if (name.indexOf('.') > 0) {
404
- intermediateValue = context.view;
405
- names = name.split('.');
406
- index = 0;
407
-
408
- /**
409
- * Using the dot notion path in `name`, we descend through the
410
- * nested objects.
411
- *
412
- * To be certain that the lookup has been successful, we have to
413
- * check if the last object in the path actually has the property
414
- * we are looking for. We store the result in `lookupHit`.
415
- *
416
- * This is specially necessary for when the value has been set to
417
- * `undefined` and we want to avoid looking up parent contexts.
418
- *
419
- * In the case where dot notation is used, we consider the lookup
420
- * to be successful even if the last "object" in the path is
421
- * not actually an object but a primitive (e.g., a string, or an
422
- * integer), because it is sometimes useful to access a property
423
- * of an autoboxed primitive, such as the length of a string.
424
- **/
425
- while (intermediateValue != null && index < names.length) {
426
- if (index === names.length - 1)
427
- lookupHit = (
428
- hasProperty(intermediateValue, names[index])
429
- || primitiveHasOwnProperty(intermediateValue, names[index])
430
- );
431
-
432
- intermediateValue = intermediateValue[names[index++]];
388
+ /**
389
+ * Creates a new context using the given view with this context
390
+ * as the parent.
391
+ */
392
+ Context.prototype.push = function push (view) {
393
+ return new Context(view, this);
394
+ };
395
+
396
+ /**
397
+ * Returns the value of the given name in this context, traversing
398
+ * up the context hierarchy if the value is absent in this context's view.
399
+ */
400
+ Context.prototype.lookup = function lookup (name) {
401
+ var cache = this.cache;
402
+
403
+ var value;
404
+ if (cache.hasOwnProperty(name)) {
405
+ value = cache[name];
406
+ } else {
407
+ var context = this, intermediateValue, names, index, lookupHit = false;
408
+
409
+ while (context) {
410
+ if (name.indexOf('.') > 0) {
411
+ intermediateValue = context.view;
412
+ names = name.split('.');
413
+ index = 0;
414
+
415
+ /**
416
+ * Using the dot notion path in `name`, we descend through the
417
+ * nested objects.
418
+ *
419
+ * To be certain that the lookup has been successful, we have to
420
+ * check if the last object in the path actually has the property
421
+ * we are looking for. We store the result in `lookupHit`.
422
+ *
423
+ * This is specially necessary for when the value has been set to
424
+ * `undefined` and we want to avoid looking up parent contexts.
425
+ *
426
+ * In the case where dot notation is used, we consider the lookup
427
+ * to be successful even if the last "object" in the path is
428
+ * not actually an object but a primitive (e.g., a string, or an
429
+ * integer), because it is sometimes useful to access a property
430
+ * of an autoboxed primitive, such as the length of a string.
431
+ **/
432
+ while (intermediateValue != null && index < names.length) {
433
+ if (index === names.length - 1)
434
+ lookupHit = (
435
+ hasProperty(intermediateValue, names[index])
436
+ || primitiveHasOwnProperty(intermediateValue, names[index])
437
+ );
438
+
439
+ intermediateValue = intermediateValue[names[index++]];
440
+ }
441
+ } else {
442
+ intermediateValue = context.view[name];
443
+
444
+ /**
445
+ * Only checking against `hasProperty`, which always returns `false` if
446
+ * `context.view` is not an object. Deliberately omitting the check
447
+ * against `primitiveHasOwnProperty` if dot notation is not used.
448
+ *
449
+ * Consider this example:
450
+ * ```
451
+ * Mustache.render("The length of a football field is {{#length}}{{length}}{{/length}}.", {length: "100 yards"})
452
+ * ```
453
+ *
454
+ * If we were to check also against `primitiveHasOwnProperty`, as we do
455
+ * in the dot notation case, then render call would return:
456
+ *
457
+ * "The length of a football field is 9."
458
+ *
459
+ * rather than the expected:
460
+ *
461
+ * "The length of a football field is 100 yards."
462
+ **/
463
+ lookupHit = hasProperty(context.view, name);
464
+ }
465
+
466
+ if (lookupHit) {
467
+ value = intermediateValue;
468
+ break;
433
469
  }
434
- } else {
435
- intermediateValue = context.view[name];
436
-
437
- /**
438
- * Only checking against `hasProperty`, which always returns `false` if
439
- * `context.view` is not an object. Deliberately omitting the check
440
- * against `primitiveHasOwnProperty` if dot notation is not used.
441
- *
442
- * Consider this example:
443
- * ```
444
- * Mustache.render("The length of a football field is {{#length}}{{length}}{{/length}}.", {length: "100 yards"})
445
- * ```
446
- *
447
- * If we were to check also against `primitiveHasOwnProperty`, as we do
448
- * in the dot notation case, then render call would return:
449
- *
450
- * "The length of a football field is 9."
451
- *
452
- * rather than the expected:
453
- *
454
- * "The length of a football field is 100 yards."
455
- **/
456
- lookupHit = hasProperty(context.view, name);
457
- }
458
470
 
459
- if (lookupHit) {
460
- value = intermediateValue;
461
- break;
471
+ context = context.parent;
462
472
  }
463
473
 
464
- context = context.parent;
474
+ cache[name] = value;
465
475
  }
466
476
 
467
- cache[name] = value;
477
+ if (isFunction(value))
478
+ value = value.call(this.view);
479
+
480
+ return value;
481
+ };
482
+
483
+ /**
484
+ * A Writer knows how to take a stream of tokens and render them to a
485
+ * string, given a context. It also maintains a cache of templates to
486
+ * avoid the need to parse the same template twice.
487
+ */
488
+ function Writer () {
489
+ this.templateCache = {
490
+ _cache: {},
491
+ set: function set (key, value) {
492
+ this._cache[key] = value;
493
+ },
494
+ get: function get (key) {
495
+ return this._cache[key];
496
+ },
497
+ clear: function clear () {
498
+ this._cache = {};
499
+ }
500
+ };
468
501
  }
469
502
 
470
- if (isFunction(value))
471
- value = value.call(this.view);
472
-
473
- return value;
474
- };
475
-
476
- /**
477
- * A Writer knows how to take a stream of tokens and render them to a
478
- * string, given a context. It also maintains a cache of templates to
479
- * avoid the need to parse the same template twice.
480
- */
481
- function Writer () {
482
- this.templateCache = {
483
- _cache: {},
484
- set: function set (key, value) {
485
- this._cache[key] = value;
486
- },
487
- get: function get (key) {
488
- return this._cache[key];
489
- },
490
- clear: function clear () {
491
- this._cache = {};
503
+ /**
504
+ * Clears all cached templates in this writer.
505
+ */
506
+ Writer.prototype.clearCache = function clearCache () {
507
+ if (typeof this.templateCache !== 'undefined') {
508
+ this.templateCache.clear();
492
509
  }
493
510
  };
494
- }
495
-
496
- /**
497
- * Clears all cached templates in this writer.
498
- */
499
- Writer.prototype.clearCache = function clearCache () {
500
- if (typeof this.templateCache !== 'undefined') {
501
- this.templateCache.clear();
502
- }
503
- };
504
-
505
- /**
506
- * Parses and caches the given `template` according to the given `tags` or
507
- * `mustache.tags` if `tags` is omitted, and returns the array of tokens
508
- * that is generated from the parse.
509
- */
510
- Writer.prototype.parse = function parse (template, tags) {
511
- var cache = this.templateCache;
512
- var cacheKey = template + ':' + (tags || mustache.tags).join(':');
513
- var isCacheEnabled = typeof cache !== 'undefined';
514
- var tokens = isCacheEnabled ? cache.get(cacheKey) : undefined;
515
-
516
- if (tokens == undefined) {
517
- tokens = parseTemplate(template, tags);
518
- isCacheEnabled && cache.set(cacheKey, tokens);
519
- }
520
- return tokens;
521
- };
522
-
523
- /**
524
- * High-level method that is used to render the given `template` with
525
- * the given `view`.
526
- *
527
- * The optional `partials` argument may be an object that contains the
528
- * names and templates of partials that are used in the template. It may
529
- * also be a function that is used to load partial templates on the fly
530
- * that takes a single argument: the name of the partial.
531
- *
532
- * If the optional `config` argument is given here, then it should be an
533
- * object with a `tags` attribute or an `escape` attribute or both.
534
- * If an array is passed, then it will be interpreted the same way as
535
- * a `tags` attribute on a `config` object.
536
- *
537
- * The `tags` attribute of a `config` object must be an array with two
538
- * string values: the opening and closing tags used in the template (e.g.
539
- * [ "<%", "%>" ]). The default is to mustache.tags.
540
- *
541
- * The `escape` attribute of a `config` object must be a function which
542
- * accepts a string as input and outputs a safely escaped string.
543
- * If an `escape` function is not provided, then an HTML-safe string
544
- * escaping function is used as the default.
545
- */
546
- Writer.prototype.render = function render (template, view, partials, config) {
547
- var tags = this.getConfigTags(config);
548
- var tokens = this.parse(template, tags);
549
- var context = (view instanceof Context) ? view : new Context(view, undefined);
550
- return this.renderTokens(tokens, context, partials, template, config);
551
- };
552
-
553
- /**
554
- * Low-level method that renders the given array of `tokens` using
555
- * the given `context` and `partials`.
556
- *
557
- * Note: The `originalTemplate` is only ever used to extract the portion
558
- * of the original template that was contained in a higher-order section.
559
- * If the template doesn't use higher-order sections, this argument may
560
- * be omitted.
561
- */
562
- Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate, config) {
563
- var buffer = '';
564
-
565
- var token, symbol, value;
566
- for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
567
- value = undefined;
568
- token = tokens[i];
569
- symbol = token[0];
570
-
571
- if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate, config);
572
- else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate, config);
573
- else if (symbol === '>') value = this.renderPartial(token, context, partials, config);
574
- else if (symbol === '&') value = this.unescapedValue(token, context);
575
- else if (symbol === 'name') value = this.escapedValue(token, context, config);
576
- else if (symbol === 'text') value = this.rawValue(token);
577
-
578
- if (value !== undefined)
579
- buffer += value;
580
- }
581
511
 
582
- return buffer;
583
- };
512
+ /**
513
+ * Parses and caches the given `template` according to the given `tags` or
514
+ * `mustache.tags` if `tags` is omitted, and returns the array of tokens
515
+ * that is generated from the parse.
516
+ */
517
+ Writer.prototype.parse = function parse (template, tags) {
518
+ var cache = this.templateCache;
519
+ var cacheKey = template + ':' + (tags || mustache.tags).join(':');
520
+ var isCacheEnabled = typeof cache !== 'undefined';
521
+ var tokens = isCacheEnabled ? cache.get(cacheKey) : undefined;
522
+
523
+ if (tokens == undefined) {
524
+ tokens = parseTemplate(template, tags);
525
+ isCacheEnabled && cache.set(cacheKey, tokens);
526
+ }
527
+ return tokens;
528
+ };
584
529
 
585
- Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate, config) {
586
- var self = this;
587
- var buffer = '';
588
- var value = context.lookup(token[1]);
530
+ /**
531
+ * High-level method that is used to render the given `template` with
532
+ * the given `view`.
533
+ *
534
+ * The optional `partials` argument may be an object that contains the
535
+ * names and templates of partials that are used in the template. It may
536
+ * also be a function that is used to load partial templates on the fly
537
+ * that takes a single argument: the name of the partial.
538
+ *
539
+ * If the optional `config` argument is given here, then it should be an
540
+ * object with a `tags` attribute or an `escape` attribute or both.
541
+ * If an array is passed, then it will be interpreted the same way as
542
+ * a `tags` attribute on a `config` object.
543
+ *
544
+ * The `tags` attribute of a `config` object must be an array with two
545
+ * string values: the opening and closing tags used in the template (e.g.
546
+ * [ "<%", "%>" ]). The default is to mustache.tags.
547
+ *
548
+ * The `escape` attribute of a `config` object must be a function which
549
+ * accepts a string as input and outputs a safely escaped string.
550
+ * If an `escape` function is not provided, then an HTML-safe string
551
+ * escaping function is used as the default.
552
+ */
553
+ Writer.prototype.render = function render (template, view, partials, config) {
554
+ var tags = this.getConfigTags(config);
555
+ var tokens = this.parse(template, tags);
556
+ var context = (view instanceof Context) ? view : new Context(view, undefined);
557
+ return this.renderTokens(tokens, context, partials, template, config);
558
+ };
589
559
 
590
- // This function is used to render an arbitrary template
591
- // in the current context by higher-order sections.
592
- function subRender (template) {
593
- return self.render(template, context, partials, config);
594
- }
560
+ /**
561
+ * Low-level method that renders the given array of `tokens` using
562
+ * the given `context` and `partials`.
563
+ *
564
+ * Note: The `originalTemplate` is only ever used to extract the portion
565
+ * of the original template that was contained in a higher-order section.
566
+ * If the template doesn't use higher-order sections, this argument may
567
+ * be omitted.
568
+ */
569
+ Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate, config) {
570
+ var buffer = '';
571
+
572
+ var token, symbol, value;
573
+ for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
574
+ value = undefined;
575
+ token = tokens[i];
576
+ symbol = token[0];
577
+
578
+ if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate, config);
579
+ else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate, config);
580
+ else if (symbol === '>') value = this.renderPartial(token, context, partials, config);
581
+ else if (symbol === '&') value = this.unescapedValue(token, context);
582
+ else if (symbol === 'name') value = this.escapedValue(token, context, config);
583
+ else if (symbol === 'text') value = this.rawValue(token);
584
+
585
+ if (value !== undefined)
586
+ buffer += value;
587
+ }
588
+
589
+ return buffer;
590
+ };
591
+
592
+ Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate, config) {
593
+ var self = this;
594
+ var buffer = '';
595
+ var value = context.lookup(token[1]);
596
+
597
+ // This function is used to render an arbitrary template
598
+ // in the current context by higher-order sections.
599
+ function subRender (template) {
600
+ return self.render(template, context, partials, config);
601
+ }
602
+
603
+ if (!value) return;
604
+
605
+ if (isArray(value)) {
606
+ for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
607
+ buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate, config);
608
+ }
609
+ } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {
610
+ buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate, config);
611
+ } else if (isFunction(value)) {
612
+ if (typeof originalTemplate !== 'string')
613
+ throw new Error('Cannot use higher-order sections without the original template');
614
+
615
+ // Extract the portion of the original template that the section contains.
616
+ value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
617
+
618
+ if (value != null)
619
+ buffer += value;
620
+ } else {
621
+ buffer += this.renderTokens(token[4], context, partials, originalTemplate, config);
622
+ }
623
+ return buffer;
624
+ };
595
625
 
596
- if (!value) return;
626
+ Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate, config) {
627
+ var value = context.lookup(token[1]);
597
628
 
598
- if (isArray(value)) {
599
- for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
600
- buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate, config);
629
+ // Use JavaScript's definition of falsy. Include empty arrays.
630
+ // See https://github.com/janl/mustache.js/issues/186
631
+ if (!value || (isArray(value) && value.length === 0))
632
+ return this.renderTokens(token[4], context, partials, originalTemplate, config);
633
+ };
634
+
635
+ Writer.prototype.indentPartial = function indentPartial (partial, indentation, lineHasNonSpace) {
636
+ var filteredIndentation = indentation.replace(/[^ \t]/g, '');
637
+ var partialByNl = partial.split('\n');
638
+ for (var i = 0; i < partialByNl.length; i++) {
639
+ if (partialByNl[i].length && (i > 0 || !lineHasNonSpace)) {
640
+ partialByNl[i] = filteredIndentation + partialByNl[i];
641
+ }
601
642
  }
602
- } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {
603
- buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate, config);
604
- } else if (isFunction(value)) {
605
- if (typeof originalTemplate !== 'string')
606
- throw new Error('Cannot use higher-order sections without the original template');
643
+ return partialByNl.join('\n');
644
+ };
607
645
 
608
- // Extract the portion of the original template that the section contains.
609
- value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
646
+ Writer.prototype.renderPartial = function renderPartial (token, context, partials, config) {
647
+ if (!partials) return;
648
+ var tags = this.getConfigTags(config);
649
+
650
+ var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
651
+ if (value != null) {
652
+ var lineHasNonSpace = token[6];
653
+ var tagIndex = token[5];
654
+ var indentation = token[4];
655
+ var indentedValue = value;
656
+ if (tagIndex == 0 && indentation) {
657
+ indentedValue = this.indentPartial(value, indentation, lineHasNonSpace);
658
+ }
659
+ var tokens = this.parse(indentedValue, tags);
660
+ return this.renderTokens(tokens, context, partials, indentedValue, config);
661
+ }
662
+ };
610
663
 
664
+ Writer.prototype.unescapedValue = function unescapedValue (token, context) {
665
+ var value = context.lookup(token[1]);
611
666
  if (value != null)
612
- buffer += value;
613
- } else {
614
- buffer += this.renderTokens(token[4], context, partials, originalTemplate, config);
615
- }
616
- return buffer;
617
- };
618
-
619
- Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate, config) {
620
- var value = context.lookup(token[1]);
621
-
622
- // Use JavaScript's definition of falsy. Include empty arrays.
623
- // See https://github.com/janl/mustache.js/issues/186
624
- if (!value || (isArray(value) && value.length === 0))
625
- return this.renderTokens(token[4], context, partials, originalTemplate, config);
626
- };
627
-
628
- Writer.prototype.indentPartial = function indentPartial (partial, indentation, lineHasNonSpace) {
629
- var filteredIndentation = indentation.replace(/[^ \t]/g, '');
630
- var partialByNl = partial.split('\n');
631
- for (var i = 0; i < partialByNl.length; i++) {
632
- if (partialByNl[i].length && (i > 0 || !lineHasNonSpace)) {
633
- partialByNl[i] = filteredIndentation + partialByNl[i];
667
+ return value;
668
+ };
669
+
670
+ Writer.prototype.escapedValue = function escapedValue (token, context, config) {
671
+ var escape = this.getConfigEscape(config) || mustache.escape;
672
+ var value = context.lookup(token[1]);
673
+ if (value != null)
674
+ return (typeof value === 'number' && escape === mustache.escape) ? String(value) : escape(value);
675
+ };
676
+
677
+ Writer.prototype.rawValue = function rawValue (token) {
678
+ return token[1];
679
+ };
680
+
681
+ Writer.prototype.getConfigTags = function getConfigTags (config) {
682
+ if (isArray(config)) {
683
+ return config;
634
684
  }
635
- }
636
- return partialByNl.join('\n');
637
- };
638
-
639
- Writer.prototype.renderPartial = function renderPartial (token, context, partials, config) {
640
- if (!partials) return;
641
- var tags = this.getConfigTags(config);
642
-
643
- var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
644
- if (value != null) {
645
- var lineHasNonSpace = token[6];
646
- var tagIndex = token[5];
647
- var indentation = token[4];
648
- var indentedValue = value;
649
- if (tagIndex == 0 && indentation) {
650
- indentedValue = this.indentPartial(value, indentation, lineHasNonSpace);
685
+ else if (config && typeof config === 'object') {
686
+ return config.tags;
651
687
  }
652
- var tokens = this.parse(indentedValue, tags);
653
- return this.renderTokens(tokens, context, partials, indentedValue, config);
654
- }
655
- };
688
+ else {
689
+ return undefined;
690
+ }
691
+ };
656
692
 
657
- Writer.prototype.unescapedValue = function unescapedValue (token, context) {
658
- var value = context.lookup(token[1]);
659
- if (value != null)
660
- return value;
661
- };
662
-
663
- Writer.prototype.escapedValue = function escapedValue (token, context, config) {
664
- var escape = this.getConfigEscape(config) || mustache.escape;
665
- var value = context.lookup(token[1]);
666
- if (value != null)
667
- return (typeof value === 'number' && escape === mustache.escape) ? String(value) : escape(value);
668
- };
669
-
670
- Writer.prototype.rawValue = function rawValue (token) {
671
- return token[1];
672
- };
673
-
674
- Writer.prototype.getConfigTags = function getConfigTags (config) {
675
- if (isArray(config)) {
676
- return config;
677
- }
678
- else if (config && typeof config === 'object') {
679
- return config.tags;
680
- }
681
- else {
682
- return undefined;
683
- }
684
- };
693
+ Writer.prototype.getConfigEscape = function getConfigEscape (config) {
694
+ if (config && typeof config === 'object' && !isArray(config)) {
695
+ return config.escape;
696
+ }
697
+ else {
698
+ return undefined;
699
+ }
700
+ };
701
+
702
+ var mustache = {
703
+ name: 'mustache.js',
704
+ version: '4.1.0',
705
+ tags: [ '{{', '}}' ],
706
+ clearCache: undefined,
707
+ escape: undefined,
708
+ parse: undefined,
709
+ render: undefined,
710
+ Scanner: undefined,
711
+ Context: undefined,
712
+ Writer: undefined,
713
+ /**
714
+ * Allows a user to override the default caching strategy, by providing an
715
+ * object with set, get and clear methods. This can also be used to disable
716
+ * the cache by setting it to the literal `undefined`.
717
+ */
718
+ set templateCache (cache) {
719
+ defaultWriter.templateCache = cache;
720
+ },
721
+ /**
722
+ * Gets the default or overridden caching object from the default writer.
723
+ */
724
+ get templateCache () {
725
+ return defaultWriter.templateCache;
726
+ }
727
+ };
728
+
729
+ // All high-level mustache.* functions use this writer.
730
+ var defaultWriter = new Writer();
685
731
 
686
- Writer.prototype.getConfigEscape = function getConfigEscape (config) {
687
- if (config && typeof config === 'object' && !isArray(config)) {
688
- return config.escape;
689
- }
690
- else {
691
- return undefined;
692
- }
693
- };
694
-
695
- var mustache = {
696
- name: 'mustache.js',
697
- version: '4.2.0',
698
- tags: [ '{{', '}}' ],
699
- clearCache: undefined,
700
- escape: undefined,
701
- parse: undefined,
702
- render: undefined,
703
- Scanner: undefined,
704
- Context: undefined,
705
- Writer: undefined,
706
732
  /**
707
- * Allows a user to override the default caching strategy, by providing an
708
- * object with set, get and clear methods. This can also be used to disable
709
- * the cache by setting it to the literal `undefined`.
733
+ * Clears all cached templates in the default writer.
710
734
  */
711
- set templateCache (cache) {
712
- defaultWriter.templateCache = cache;
713
- },
735
+ mustache.clearCache = function clearCache () {
736
+ return defaultWriter.clearCache();
737
+ };
738
+
714
739
  /**
715
- * Gets the default or overridden caching object from the default writer.
740
+ * Parses and caches the given template in the default writer and returns the
741
+ * array of tokens it contains. Doing this ahead of time avoids the need to
742
+ * parse templates on the fly as they are rendered.
716
743
  */
717
- get templateCache () {
718
- return defaultWriter.templateCache;
719
- }
720
- };
721
-
722
- // All high-level mustache.* functions use this writer.
723
- var defaultWriter = new Writer();
724
-
725
- /**
726
- * Clears all cached templates in the default writer.
727
- */
728
- mustache.clearCache = function clearCache () {
729
- return defaultWriter.clearCache();
730
- };
731
-
732
- /**
733
- * Parses and caches the given template in the default writer and returns the
734
- * array of tokens it contains. Doing this ahead of time avoids the need to
735
- * parse templates on the fly as they are rendered.
736
- */
737
- mustache.parse = function parse (template, tags) {
738
- return defaultWriter.parse(template, tags);
739
- };
740
-
741
- /**
742
- * Renders the `template` with the given `view`, `partials`, and `config`
743
- * using the default writer.
744
- */
745
- mustache.render = function render (template, view, partials, config) {
746
- if (typeof template !== 'string') {
747
- throw new TypeError('Invalid template! Template should be a "string" ' +
748
- 'but "' + typeStr(template) + '" was given as the first ' +
749
- 'argument for mustache#render(template, view, partials)');
750
- }
744
+ mustache.parse = function parse (template, tags) {
745
+ return defaultWriter.parse(template, tags);
746
+ };
747
+
748
+ /**
749
+ * Renders the `template` with the given `view`, `partials`, and `config`
750
+ * using the default writer.
751
+ */
752
+ mustache.render = function render (template, view, partials, config) {
753
+ if (typeof template !== 'string') {
754
+ throw new TypeError('Invalid template! Template should be a "string" ' +
755
+ 'but "' + typeStr(template) + '" was given as the first ' +
756
+ 'argument for mustache#render(template, view, partials)');
757
+ }
758
+
759
+ return defaultWriter.render(template, view, partials, config);
760
+ };
751
761
 
752
- return defaultWriter.render(template, view, partials, config);
753
- };
762
+ // Export the escaping function so that the user may override it.
763
+ // See https://github.com/janl/mustache.js/issues/244
764
+ mustache.escape = escapeHtml;
754
765
 
755
- // Export the escaping function so that the user may override it.
756
- // See https://github.com/janl/mustache.js/issues/244
757
- mustache.escape = escapeHtml;
766
+ // Export these mainly for testing, but also for advanced usage.
767
+ mustache.Scanner = Scanner;
768
+ mustache.Context = Context;
769
+ mustache.Writer = Writer;
758
770
 
759
- // Export these mainly for testing, but also for advanced usage.
760
- mustache.Scanner = Scanner;
761
- mustache.Context = Context;
762
- mustache.Writer = Writer;
771
+ return mustache;
763
772
 
764
- export default mustache;
773
+ })));