|
37 | 37 | var oldDash = window._;
|
38 | 38 |
|
39 | 39 | /** Used to match empty strings in compiled templates */
|
40 |
| - var reEmptyStringEvaluate = /\b__p \+= '';/g, |
41 |
| - reEmptyStringInterpolate = /\b__p \+= '' \+/g, |
42 |
| - reEmptyStringHybrid = /\b__t\) \+\n'';/g; |
| 40 | + var reEmptyStringLeading = /\b__p \+= '';/g, |
| 41 | + reEmptyStringMiddle = /\b(__p \+?=) '' \+/g, |
| 42 | + reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; |
43 | 43 |
|
44 | 44 | /** Used to insert the data object variable into compiled templates */
|
45 | 45 | var reInsertVariable = /(?:__e|__t = )\(\s*(?![\s"']|this\.)/g;
|
|
3202 | 3202 | // https://github.com/olado/doT
|
3203 | 3203 | options || (options = {});
|
3204 | 3204 |
|
3205 |
| - var isEscaping, |
| 3205 | + var endIndex, |
| 3206 | + isEscaping, |
3206 | 3207 | isEvaluating,
|
3207 | 3208 | isInterpolating,
|
| 3209 | + startIndex, |
3208 | 3210 | result,
|
| 3211 | + useWith, |
3209 | 3212 | defaults = lodash.templateSettings,
|
3210 | 3213 | escapeDelimiter = options.escape,
|
3211 | 3214 | evaluateDelimiter = options.evaluate,
|
|
3222 | 3225 | if (interpolateDelimiter == null) {
|
3223 | 3226 | interpolateDelimiter = defaults.interpolate;
|
3224 | 3227 | }
|
3225 |
| - |
3226 | 3228 | // tokenize delimiters to avoid escaping them
|
3227 | 3229 | if (escapeDelimiter) {
|
3228 | 3230 | isEscaping = text != (text = text.replace(escapeDelimiter, tokenizeEscape));
|
|
3231 | 3233 | isInterpolating = text != (text = text.replace(interpolateDelimiter, tokenizeInterpolate));
|
3232 | 3234 | }
|
3233 | 3235 | if (evaluateDelimiter) {
|
| 3236 | + startIndex = tokenized.length; |
3234 | 3237 | isEvaluating = text != (text = text.replace(evaluateDelimiter, tokenizeEvaluate));
|
| 3238 | + endIndex = tokenized.length - 1; |
| 3239 | + } |
| 3240 | + |
| 3241 | + // if `options.variable` is not specified and the template contains "evaluate" |
| 3242 | + // delimiters, inject a with-statement around all "evaluate" delimiters to |
| 3243 | + // add the data object to the top of the scope chain |
| 3244 | + if (!variable) { |
| 3245 | + variable = defaults.variable || lastVariable || 'obj'; |
| 3246 | + useWith = isEvaluating; |
| 3247 | + |
| 3248 | + if (useWith) { |
| 3249 | + tokenized[startIndex] = |
| 3250 | + tokenized[startIndex].slice(0, 3) + |
| 3251 | + '__with (' + variable + ') {\n' + |
| 3252 | + tokenized[startIndex].slice(3); |
| 3253 | + |
| 3254 | + tokenized[endIndex] = |
| 3255 | + tokenized[endIndex].slice(0, -8) + |
| 3256 | + '}__\n' + |
| 3257 | + tokenized[endIndex].slice(-8); |
| 3258 | + } |
3235 | 3259 | }
|
| 3260 | + // memoize `reDoubleVariable` |
| 3261 | + if (variable != lastVariable) { |
| 3262 | + lastVariable = variable; |
| 3263 | + reDoubleVariable = RegExp('(
EDBE
[(\\s])' + variable + '\\.' + variable + '\\b', 'g'); |
| 3264 | + } |
| 3265 | + |
| 3266 | + var strInsertVariable = '$&' + variable + '.', |
| 3267 | + strDoubleVariable = '$1__d'; |
3236 | 3268 |
|
3237 | 3269 | // escape characters that cannot be included in string literals and
|
3238 | 3270 | // detokenize delimiter code snippets
|
3239 |
| - text = "__p='" + text |
| 3271 | + text = "__p = '" + text |
3240 | 3272 | .replace(reUnescapedString, escapeStringChar)
|
3241 | 3273 | .replace(reToken, detokenize) + "';\n";
|
3242 | 3274 |
|
3243 | 3275 | // clear stored code snippets
|
3244 | 3276 | tokenized.length = 0;
|
3245 | 3277 |
|
3246 |
| - // strip concating empty strings |
3247 |
| - if (isInterpolating) { |
3248 |
| - text = text.replace(reEmptyStringInterpolate, '__p \+='); |
3249 |
| - } |
3250 |
| - if (isEvaluating) { |
3251 |
| - text = text.replace(reEmptyStringEvaluate, ''); |
3252 |
| - if (isInterpolating) { |
3253 |
| - text = text.replace(reEmptyStringHybrid, '__t);'); |
3254 |
| - } |
3255 |
| - } |
| 3278 | + // find the start and end indexes of the with-statement |
| 3279 | + if (useWith) { |
| 3280 | + startIndex = text.indexOf('__with'); |
| 3281 | + endIndex = text.indexOf('}__', startIndex + 12); |
| 3282 | + } |
| 3283 | + |
| 3284 | + // inject data object references outside of the with-statement |
| 3285 | + text = (useWith ? text.slice(0, startIndex) : text) |
| 3286 | + .replace(reInsertVariable, strInsertVariable) |
| 3287 | + .replace(reDoubleVariable, strDoubleVariable) + |
| 3288 | + (useWith |
| 3289 | + ? text.slice(startIndex + 2, endIndex + 1) + |
| 3290 | + text.slice(endIndex + 3) |
| 3291 | + .replace(reInsertVariable, strInsertVariable) |
| 3292 | + .replace(reDoubleVariable, strDoubleVariable) |
| 3293 | + : '' |
| 3294 | + ); |
3256 | 3295 |
|
3257 |
| - if (!variable) { |
3258 |
| - variable = defaults.variable; |
3259 |
| - |
3260 |
| - // if `options.variable` is not specified or the template contains "evaluate" |
3261 |
| - // delimiters, add the data object to the top of the scope chain |
3262 |
| - if (isEvaluating || !variable) { |
3263 |
| - text = 'with (' + variable + ' || {}) {\n' + text + '\n}\n'; |
3264 |
| - } |
3265 |
| - // else insert data object references to avoid using a with-statement |
3266 |
| - else { |
3267 |
| - if (variable != lastVariable) { |
3268 |
| - lastVariable = variable; |
3269 |
| - reDoubleVariable = RegExp('([(\\s])(' + variable + '\\.' + variable + ')\\b', 'g'); |
3270 |
| - } |
3271 |
| - text = text |
3272 |
| - .replace(reInsertVariable, '$&' + variable + '.') |
3273 |
| - .replace(reDoubleVariable, '$1($2 || ' + variable + ')'); |
3274 |
| - } |
3275 |
| - } |
| 3296 | + // cleanup compiled code by stripping empty strings |
| 3297 | + text = (isEvaluating ? text.replace(reEmptyStringLeading, '') : text) |
| 3298 | + .replace(reEmptyStringMiddle, '$1') |
| 3299 | + .replace(reEmptyStringTrailing, '$1;'); |
3276 | 3300 |
|
| 3301 | + // wrap function body |
3277 | 3302 | text = 'function(' + variable + ') {\n' +
|
| 3303 | + (useWith |
| 3304 | + ? variable + ' || (' + variable + ' = {});\n' |
| 3305 | + : '' |
| 3306 | + ) + |
3278 | 3307 | 'var __p' +
|
3279 | 3308 | (isInterpolating
|
3280 | 3309 | ? ', __t'
|
3281 | 3310 | : ''
|
3282 | 3311 | ) +
|
| 3312 | + ', __d = ' + variable + '.' + variable + ' || ' + variable + |
3283 | 3313 | (isEscaping
|
3284 | 3314 | ? ', __e = _.escape'
|
3285 | 3315 | : ''
|
|
0 commit comments