Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0dc88bb

Browse files
committed
Fix template regressions. [Closes#44]
Former-commit-id: 15e98d86c290fea74780822b49b5d71e54064e01
1 parent971a26c commit0dc88bb

File tree

2 files changed

+61
-68
lines changed

2 files changed

+61
-68
lines changed

‎lodash.js‎

Lines changed: 37 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,10 @@
5050
/** Used to detect delimiter values that should be processed by `tokenizeEvaluate` */
5151
varreComplexDelimiter=/[-+=!~*%&^<>|{(\/]|\[\D|\b(?:delete|in|instanceof|new|typeof|void)\b/;
5252

53-
/** Used to match code generated in place of template delimiters */
54-
varreDelimiterCodeLeading=/^';\n/,
55-
reDelimiterCodeMiddle=/^'\+\n/,
56-
reDelimiterCodeTrailing=/(?:__p\+='|\+\n')$/;
57-
5853
/** Used to match empty string literals in compiled template source */
5954
varreEmptyStringLeading=/\b__p\+='';/g,
60-
reEmptyStringMiddle=/\b(__p\+?=)''\+/g,
61-
reEmptyStringTrailing=/(__w?e\(.*?\)|\b__w?t\))\+\n'';/g;
55+
reEmptyStringMiddle=/\b(__p\+=)''\+/g,
56+
reEmptyStringTrailing=/(__e\(.*?\)|\b__t\))\+\n'';/g;
6257

6358
/** Used to insert the data object variable into compiled template source */
6459
varreInsertVariable=/(?:__e|__t=)\(\s*(?![\d\s"']|this\.)/g;
@@ -672,12 +667,10 @@
672667
varindex=tokenized.length;
673668
if(value){
674669
tokenized[index]="';\n"+value+";\n__p += '"
675-
}
676-
elseif(escapeValue){
677-
tokenized[index]="' +\n__we("+escapeValue+") +\n'";
678-
}
679-
elseif(interpolateValue){
680-
tokenized[index]="' +\n((__wt = ("+interpolateValue+")) == null ? '' : __wt) +\n'";
670+
}elseif(escapeValue){
671+
tokenized[index]="' +\n__e("+escapeValue+") +\n'";
672+
}elseif(interpolateValue){
673+
tokenized[index]="' +\n((__t = ("+interpolateValue+")) == null ? '' : __t) +\n'";
681674
}
682675
returntoken+index;
683676
}
@@ -3307,11 +3300,8 @@
33073300
// https://github.com/olado/doT
33083301
options||(options={});
33093302

3310-
varendIndex,
3311-
isEvaluating,
3312-
startIndex,
3303+
varisEvaluating,
33133304
result,
3314-
useWith,
33153305
escapeDelimiter=options.escape,
33163306
evaluateDelimiter=options.evaluate,
33173307
interpolateDelimiter=options.interpolate,
@@ -3337,83 +3327,63 @@
33373327
text=text.replace(interpolateDelimiter,tokenizeInterpolate);
33383328
}
33393329
if(evaluateDelimiter!=lastEvaluateDelimiter){
3330+
// generate `reEvaluateDelimiter` to match `_.templateSettings.evaluate`
3331+
// and internal `<e%- %>`, `<e%= %>` delimiters
33403332
lastEvaluateDelimiter=evaluateDelimiter;
33413333
reEvaluateDelimiter=RegExp(
33423334
(evaluateDelimiter ?evaluateDelimiter.source :'($^)')+
33433335
'|<e%-([\\s\\S]+?)%>|<e%=([\\s\\S]+?)%>'
33443336
,'g');
33453337
}
3346-
startIndex=tokenized.length;
3338+
isEvaluating=tokenized.length;
33473339
text=text.replace(reEvaluateDelimiter,tokenizeEvaluate);
3348-
endIndex=tokenized.length-1;
3349-
isEvaluating=startIndex<=endIndex;
3350-
3351-
// if `options.variable` is not specified and the template contains "evaluate"
3352-
// delimiters, inject a with-statement around all "evaluate" delimiters to
3353-
// add the data object to the top of the scope chain
3354-
if(!variable){
3355-
variable=settings.variable||lastVariable||'obj';
3356-
useWith=isEvaluating;
3357-
3358-
if(useWith){
3359-
tokenized[startIndex]="';\n__with ("+variable+') {\n'+tokenized[startIndex]
3360-
.replace(reDelimiterCodeLeading,'')
3361-
.replace(reDelimiterCodeMiddle,'__p += ');
3362-
3363-
tokenized[endIndex]=tokenized[endIndex]
3364-
.replace(reDelimiterCodeTrailing,'')+"\n}__\n__p += '";
3365-
}
3366-
}
3367-
3368-
varstrInsertVariable='$&'+variable+'.',
3369-
strDoubleVariable='$1__d';
3340+
isEvaluating=isEvaluating!=tokenized.length;
33703341

33713342
// escape characters that cannot be included in string literals and
33723343
// detokenize delimiter code snippets
3373-
text="__p = '"+text
3344+
text="__p+= '"+text
33743345
.replace(reUnescapedString,escapeStringChar)
33753346
.replace(reToken,detokenize)+"';\n";
33763347

33773348
// clear stored code snippets
33783349
tokenized.length=0;
33793350

3380-
// find the start and end indexes of the with-statement
3381-
if(useWith){
3382-
startIndex=text.indexOf('__with');
3383-
endIndex=text.indexOf('}__',startIndex+10);
3384-
}
3385-
// memoize `reDoubleVariable`
3386-
if(variable!=lastVariable){
3387-
lastVariable=variable;
3388-
reDoubleVariable=RegExp('([(\\s])'+variable+'\\.'+variable+'\\b','g');
3389-
}
3390-
// prepend data object references to property names outside of the with-statement
3391-
text=(useWith ?text.slice(0,startIndex) :text)
3392-
.replace(reInsertVariable,strInsertVariable)
3393-
.replace(reDoubleVariable,strDoubleVariable)+
3394-
(useWith
3395-
?text.slice(startIndex+2,endIndex+1)+
3396-
text.slice(endIndex+3)
3397-
.replace(reInsertVariable,strInsertVariable)
3398-
.replace(reDoubleVariable,strDoubleVariable)
3399-
:''
3400-
);
3351+
// if `options.variable` is not specified and the template contains "evaluate"
3352+
// delimiters, wrap a with-statement around the generated code to add the
3353+
// data object to the top of the scope chain
3354+
if(!variable){
3355+
variable=settings.variable||lastVariable||'obj';
3356+
3357+
if(isEvaluating){
3358+
text='with ('+variable+') {\n'+text+'\n}\n';
3359+
}
3360+
else{
3361+
if(variable!=lastVariable){
3362+
// generate `reDoubleVariable` to match references like `obj.obj` inside
3363+
// transformed "escape" and "interpolate" delimiters
3364+
lastVariable=variable;
3365+
reDoubleVariable=RegExp('(\\(\\s*)'+variable+'\\.'+variable+'\\b','g');
3366+
}
3367+
// avoid a with-statement by prepending data object references to property names
3368+
text=text
3369+
.replace(reInsertVariable,'$&'+variable+'.')
3370+
.replace(reDoubleVariable,'$1__d');
3371+
}
3372+
}
34013373

34023374
// cleanup code by stripping empty strings
3403-
text=(isEvaluating ?text.replace(reEmptyStringLeading,'') :text)
3375+
text=(isEvaluating ?text.replace(reEmptyStringLeading,'') :text)
34043376
.replace(reEmptyStringMiddle,'$1')
34053377
.replace(reEmptyStringTrailing,'$1;');
34063378

34073379
// frame code as the function body
34083380
text='function('+variable+') {\n'+
34093381
variable+' || ('+variable+' = {});\n'+
3410-
'var __p, __t, __wt'+
3411-
', __d = '+variable+'.'+variable+' || '+variable+
3412-
', __e = _.escape, __we = __e'+
3382+
'var __t, __p = \'\', __e = _.escape'+
34133383
(isEvaluating
34143384
?', __j = Array.prototype.join;\n'+
34153385
'function print() { __p += __j.call(arguments, \'\') }\n'
3416-
:';\n'
3386+
:', __d = '+variable+'.'+variable+' || '+variable+';\n'
34173387
)+
34183388
text+
34193389
'return __p\n}';

‎test/test.js‎

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -771,9 +771,32 @@
771771
varcompiled=_.template(key),
772772
data={'a':1,'b':2};
773773

774-
equal(compiled(data),value);
774+
equal(compiled(data),value,key);
775775
});
776776
});
777+
778+
test('should allow referencing variables declared in "evaluate" delimiters from other delimiters',function(){
779+
varcompiled=_.template('<% var b = a; %><%= b.value %>'),
780+
data={'a':{'value':1}};
781+
782+
equal(compiled(data),'1');
783+
});
784+
785+
test('should work when passing `options.variable`',function(){
786+
varcompiled=_.template(
787+
'<% _.forEach( data.a, function( value ) { %>'+
788+
'<%= value.valueOf() %>'+
789+
'<% }) %>',null,{'variable':'data'}
790+
);
791+
792+
vardata={'a':[1,2,3]};
793+
794+
try{
795+
equal(compiled(data),'123');
796+
}catch(e){
797+
ok(false);
798+
}
799+
});
777800
}());
778801

779802
/*--------------------------------------------------------------------------*/

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp