Просмотр исходного кода

merge with the previous solution

pull/703/head
Yotam Madem 6 лет назад
Родитель
Сommit
d06d0bf002
2 измененных файлов: 40 добавлений и 43 удалений
  1. +34
    -40
      mustache.js
  2. +6
    -3
      test/parse-test.js

+ 34
- 40
mustache.js Просмотреть файл

@@ -124,6 +124,8 @@
var spaces = []; // Indices of whitespace tokens on the current line var spaces = []; // Indices of whitespace tokens on the current line
var hasTag = false; // Is there a {{tag}} on the current line? var hasTag = false; // Is there a {{tag}} on the current line?
var nonSpace = false; // Is there a non-space char on the current line? var nonSpace = false; // Is there a non-space char on the current line?
var indentation = ''; // Tracks indentation for tags that use it
var tagIndex = 0; // Stores a count of number of tags encountered on a line


// Strips all whitespace tokens array for the current line // Strips all whitespace tokens array for the current line
// if there was a {{#tag}} on it and otherwise only space. // if there was a {{#tag}} on it and otherwise only space.
@@ -168,17 +170,23 @@
chr = value.charAt(i); chr = value.charAt(i);


if (isWhitespace(chr)) { if (isWhitespace(chr)) {
spaces.push(tokens.length);
spaces.push(tokens.length);
if (!nonSpace)
indentation += chr;
} else { } else {
nonSpace = true; nonSpace = true;
indentation = '';
} }


tokens.push([ 'text', chr, start, start + 1 ]); tokens.push([ 'text', chr, start, start + 1 ]);
start += 1; start += 1;


// Check for whitespace on the current line. // Check for whitespace on the current line.
if (chr === '\n')
if (chr === '\n'){
stripSpace(); stripSpace();
indentation = '';
tagIndex = 0;
}
} }
} }


@@ -191,10 +199,6 @@
// Get the tag type. // Get the tag type.
type = scanner.scan(tagRe) || 'name'; type = scanner.scan(tagRe) || 'name';


if (type == '>') {
spaces = [];
}
scanner.scan(whiteRe); scanner.scan(whiteRe);


// Get the tag value. // Get the tag value.
@@ -216,6 +220,13 @@
throw new Error('Unclosed tag at ' + scanner.pos); throw new Error('Unclosed tag at ' + scanner.pos);


token = [ type, value, start, scanner.pos ]; token = [ type, value, start, scanner.pos ];

if (type == '>' && tagIndex == 0) {
token.push(indentation);
}

tagIndex ++;

tokens.push(token); tokens.push(token);


if (type === '#' || type === '^') { if (type === '#' || type === '^') {
@@ -237,6 +248,8 @@
} }
} }


stripSpace();

// Make sure there are no open sections when we're done. // Make sure there are no open sections when we're done.
openSection = sections.pop(); openSection = sections.pop();


@@ -533,7 +546,6 @@
*/ */
Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate, tags) { Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate, tags) {
var buffer = ''; var buffer = '';
var indentationContext = {spacer: '', active: true};


var token, symbol, value; var token, symbol, value;
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) { for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
@@ -543,35 +555,18 @@


if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate); if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);
else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate); else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);
else if (symbol === '>') value = this.renderPartial(token, context, partials, tags, indentationContext);
else if (symbol === '>') value = this.renderPartial(token, context, partials, tags);
else if (symbol === '&') value = this.unescapedValue(token, context); else if (symbol === '&') value = this.unescapedValue(token, context);
else if (symbol === 'name') value = this.escapedValue(token, context); else if (symbol === 'name') value = this.escapedValue(token, context);
else if (symbol === 'text') value = this.rawValue(token); else if (symbol === 'text') value = this.rawValue(token);


if (value !== undefined) { if (value !== undefined) {
this.updateIndentationContext(indentationContext, value);
buffer += value; buffer += value;
} }
} }
return buffer; return buffer;
}; };


Writer.prototype.updateIndentationContext = function updateIndentationContext (indentationContext, value) {
for (var j = 0; j < value.length; j++) {
if (value[j] == '\n') {
indentationContext.active = true;
indentationContext.spacer = '';
} else if (isWhitespace(value[j])) {
if (indentationContext.active) {
indentationContext.spacer += value[j];
}
} else {
indentationContext.active = false;
indentationContext.spacer = '';
}
}
};

Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate) { Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate) {
var self = this; var self = this;
var buffer = ''; var buffer = '';
@@ -615,30 +610,29 @@
return this.renderTokens(token[4], context, partials, originalTemplate); return this.renderTokens(token[4], context, partials, originalTemplate);
}; };


Writer.prototype.renderPartial = function renderPartial (token, context, partials, tags, indentationContext) {
Writer.prototype.renderPartial = function renderPartial (token, context, partials, tags) {
if (!partials) return; if (!partials) return;


var value = isFunction(partials) ? partials(token[1]) : partials[token[1]]; var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
if (value != null) { if (value != null) {
var indentedValue = this.indent(value, indentationContext);
return this.renderTokens(this.parse(indentedValue, tags), context, partials, value);
var indentation = token[4];
var partialVal = this.indentPartial(value, indentation);
return this.renderTokens(this.parse(partialVal, tags), context, partials, value);
} }
}; };


Writer.prototype.indent = function indent (value, indentationContext) {
var indentedValue = '';
var val = value + '$';
var lines = val.split('\n');
for (var i=0; i<lines.length; i++) {
if (i == 0) {
indentedValue += lines[i];
} else if (lines[i] == '$') {
indentedValue += '\n$';
} else {
indentedValue += ('\n' + indentationContext.spacer + lines[i]);
Writer.prototype.indentPartial = function indentPartial (value, indentation) {
if (!indentation || indentation.length == 0) {
return value;
}
var filteredIndentation = indentation.replace(/[^ \t]/g, '');
var partialByNl = value.split('\n');
for (var i = 0; i < partialByNl.length; i++) {
if (partialByNl[i].length) {
partialByNl[i] = filteredIndentation + partialByNl[i];
} }
} }
return indentedValue.substring(0, indentedValue.length-1); // remove the $
return partialByNl.join('\n');
}; };


Writer.prototype.unescapedValue = function unescapedValue (token, context) { Writer.prototype.unescapedValue = function unescapedValue (token, context) {


+ 6
- 3
test/parse-test.js Просмотреть файл

@@ -40,9 +40,12 @@ var expectations = {
'a\n{{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [ [ '#', 'b', 9, 15, [], 16 ] ], 23 ], [ 'text', 'b', 30, 31 ] ], 'a\n{{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 2, 8, [ [ '#', 'b', 9, 15, [], 16 ] ], 23 ], [ 'text', 'b', 30, 31 ] ],
'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [], 17 ] ], 24 ], [ 'text', 'b', 31, 32 ] ], 'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}}\nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [], 17 ] ], 24 ], [ 'text', 'b', 31, 32 ] ],
'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [], 17 ] ], 24 ], [ 'text', 'b', 32, 33 ] ], 'a\n {{#a}}\n{{#b}}\n{{/b}}\n{{/a}} \nb' : [ [ 'text', 'a\n', 0, 2 ], [ '#', 'a', 3, 9, [ [ '#', 'b', 10, 16, [], 17 ] ], 24 ], [ 'text', 'b', 32, 33 ] ],
'{{>abc}}' : [ [ '>', 'abc', 0, 8 ] ],
'{{> abc }}' : [ [ '>', 'abc', 0, 10 ] ],
'{{ > abc }}' : [ [ '>', 'abc', 0, 11 ] ],
'{{>abc}}' : [ [ '>', 'abc', 0, 8, ''] ],
'{{> abc }}' : [ [ '>', 'abc', 0, 10, ''] ],
'{{ > abc }}' : [ [ '>', 'abc', 0, 11, ''] ],
' {{> abc }}\n' : [ [ '>', 'abc', 2, 12, ' '] ],
' {{> abc }} {{> abc }}\n' : [ [ '>', 'abc', 2, 12, ' '], [ '>', 'abc', 13, 23] ],
'{{ > abc }}' : [ [ '>', 'abc', 0, 11, ''] ],
'{{=<% %>=}}' : [ [ '=', '<% %>', 0, 11 ] ], '{{=<% %>=}}' : [ [ '=', '<% %>', 0, 11 ] ],
'{{= <% %> =}}' : [ [ '=', '<% %>', 0, 13 ] ], '{{= <% %> =}}' : [ [ '=', '<% %>', 0, 13 ] ],
'{{=<% %>=}}<%={{ }}=%>' : [ [ '=', '<% %>', 0, 11 ], [ '=', '{{ }}', 11, 22 ] ], '{{=<% %>=}}<%={{ }}=%>' : [ [ '=', '<% %>', 0, 11 ], [ '=', '{{ }}', 11, 22 ] ],


Загрузка…
Отмена
Сохранить