Skip to content

Commit ae9588d

Browse files
authored
fix: maintain outer context (#42)
1 parent 5b91727 commit ae9588d

File tree

2 files changed

+34
-48
lines changed

2 files changed

+34
-48
lines changed

domUtil/template.js

Lines changed: 28 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -66,19 +66,22 @@ function getValueFromContext(exp, context) {
6666
function extractElseif(ifExps, sourcesInsideBlock) {
6767
var exps = [ifExps];
6868
var sourcesInsideIf = [];
69-
69+
var otherIfCount = 0;
7070
var start = 0;
71-
var i, len, source;
72-
73-
for (i = 0, len = sourcesInsideBlock.length; i < len; i += 1) {
74-
source = sourcesInsideBlock[i];
7571

76-
if (source.indexOf('elseif') > -1 || source === 'else') {
72+
// eslint-disable-next-line complexity
73+
forEach(sourcesInsideBlock, function(source, index) {
74+
if (source.indexOf('if') === 0) {
75+
otherIfCount += 1;
76+
} else if (source === '/if') {
77+
otherIfCount -= 1;
78+
} else if (!otherIfCount && (source.indexOf('elseif') === 0 || source === 'else')) {
7779
exps.push(source === 'else' ? ['true'] : source.split(' ').slice(1));
78-
sourcesInsideIf.push(sourcesInsideBlock.slice(start, i));
79-
start = i + 1;
80+
sourcesInsideIf.push(sourcesInsideBlock.slice(start, index));
81+
start = index + 1;
8082
}
81-
}
83+
});
84+
8285
sourcesInsideIf.push(sourcesInsideBlock.slice(start));
8386

8487
return {
@@ -129,9 +132,9 @@ function handleEach(exps, sourcesInsideBlock, context) {
129132
forEach(collection, function(item, key) {
130133
additionalContext[additionalKey] = key;
131134
additionalContext['@this'] = item;
132-
extend(additionalContext, context);
135+
extend(context, additionalContext);
133136

134-
result += compile(sourcesInsideBlock.slice(), additionalContext);
137+
result += compile(sourcesInsideBlock.slice(), context);
135138
});
136139

137140
return result;
@@ -153,7 +156,7 @@ function handleWith(exps, sourcesInsideBlock, context) {
153156
var additionalContext = {};
154157
additionalContext[alias] = result;
155158

156-
return compile(sourcesInsideBlock, extend(additionalContext, context)) || '';
159+
return compile(sourcesInsideBlock, extend(context, additionalContext)) || '';
157160
}
158161

159162
/**
@@ -171,25 +174,6 @@ function extractSourcesInsideBlock(sources, start, end) {
171174
return sourcesInsideBlock;
172175
}
173176

174-
/**
175-
* Concatenate the strings between previous and next of the base string in place.
176-
* @param {Array.<string>} sources - array of sources
177-
* @param {number} index - index of base string
178-
* @private
179-
*/
180-
function concatPrevAndNextString(source, index) {
181-
var start = Math.max(index - 1, 0);
182-
var end = Math.min(index + 1, source.length - 1);
183-
var deletedCount = end - start + 1;
184-
var result = source.splice(start, deletedCount).join('');
185-
186-
if (deletedCount < 3) {
187-
source.splice(start, 0, '', result);
188-
} else {
189-
source.splice(start, 0, result);
190-
}
191-
}
192-
193177
/**
194178
* Handle block helper function
195179
* @param {string} helperKeyword - helper keyword (ex. if, each, with)
@@ -200,37 +184,34 @@ function concatPrevAndNextString(source, index) {
200184
*/
201185
function handleBlockHelper(helperKeyword, sourcesToEnd, context) {
202186
var executeBlockHelper = BLOCK_HELPERS[helperKeyword];
203-
var startBlockIndices = [];
204-
var helperCount = 0;
205-
var index = 0;
187+
var helperCount = 1;
188+
var startBlockIndex = 0;
189+
var endBlockIndex;
190+
var index = startBlockIndex + EXPRESSION_INTERVAL;
206191
var expression = sourcesToEnd[index];
207-
var startBlockIndex;
208192

209-
do {
193+
while (helperCount && isString(expression)) {
210194
if (expression.indexOf(helperKeyword) === 0) {
211195
helperCount += 1;
212-
startBlockIndices.push(index);
213196
} else if (expression.indexOf('/' + helperKeyword) === 0) {
214197
helperCount -= 1;
215-
startBlockIndex = startBlockIndices.pop();
216-
217-
sourcesToEnd[startBlockIndex] = executeBlockHelper(
218-
sourcesToEnd[startBlockIndex].split(' ').slice(1),
219-
extractSourcesInsideBlock(sourcesToEnd, startBlockIndex, index),
220-
context
221-
);
222-
concatPrevAndNextString(sourcesToEnd, startBlockIndex);
223-
index = startBlockIndex - EXPRESSION_INTERVAL;
198+
endBlockIndex = index;
224199
}
225200

226201
index += EXPRESSION_INTERVAL;
227202
expression = sourcesToEnd[index];
228-
} while (helperCount && isString(expression));
203+
}
229204

230205
if (helperCount) {
231206
throw Error(helperKeyword + ' needs {{/' + helperKeyword + '}} expression.');
232207
}
233208

209+
sourcesToEnd[startBlockIndex] = executeBlockHelper(
210+
sourcesToEnd[startBlockIndex].split(' ').slice(1),
211+
extractSourcesInsideBlock(sourcesToEnd, startBlockIndex, endBlockIndex),
212+
context
213+
);
214+
234215
return sourcesToEnd;
235216
}
236217

test/template.spec.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ describe('block helper', function() {
101101
expect(function() {
102102
return template('{{each arr}}', {});
103103
}).toThrowError('each needs {{/each}} expression.');
104-
105104
expect(function() {
106105
return template('{{with 1 as one}}', {});
107106
}).toThrowError('with needs {{/with}} expression.');
@@ -238,6 +237,12 @@ describe('{{each ...}} @this @index @key {{/each}}', function() {
238237
second: [4, 5, 6]
239238
};
240239
expect(template(source, context)).toBe('456456456');
240+
241+
source = '{{each doubleArr}}{{each @this}}{{@this}}{{/each}}{{/each}}';
242+
context = {
243+
doubleArr: [[1, 2, 3], [4, 5, 6]]
244+
};
245+
expect(template(source, context)).toBe('123456');
241246
});
242247
});
243248

0 commit comments

Comments
 (0)