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

make the partials work exactly as the spec

pull/703/head
Yotam Madem 6 лет назад
Родитель
Сommit
ceff8d8852
3 измененных файлов: 140 добавлений и 14 удалений
  1. +23
    -11
      mustache.js
  2. +112
    -0
      test/partial-tests.js
  3. +5
    -3
      test/render-test.js

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

@@ -130,7 +130,7 @@
function stripSpace () {
if (hasTag && !nonSpace) {
while (spaces.length)
delete tokens[spaces.pop()];
delete tokens[spaces.pop()];
} else {
spaces = [];
}
@@ -168,7 +168,7 @@
chr = value.charAt(i);

if (isWhitespace(chr)) {
spaces.push(tokens.length);
spaces.push(tokens.length);
} else {
nonSpace = true;
}
@@ -185,11 +185,16 @@
// Match the opening tag.
if (!scanner.scan(openingTagRe))
break;
hasTag = true;

// Get the tag type.
type = scanner.scan(tagRe) || 'name';

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

// Get the tag value.
@@ -238,7 +243,7 @@
if (openSection)
throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);

return nestTokens(squashTokens(tokens));
return nestTokens(squashTokens(tokens));
}

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

var token, symbol, value;
for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
@@ -554,11 +559,15 @@
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])) {
indentationContext.spacer += value[j];
if (indentationContext.active) {
indentationContext.spacer += value[j];
}
} else {
indentationContext.spacer += ' ';
indentationContext.active = false;
indentationContext.spacer = '';
}
}
};
@@ -611,22 +620,25 @@

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

Writer.prototype.indent = function indent (value, indentationContext) {
var indentedValue = '';
var lines = value.split('\n');
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]);
}
}
return indentedValue;
return indentedValue.substring(0, indentedValue.length-1); // remove the $
};

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


+ 112
- 0
test/partial-tests.js Просмотреть файл

@@ -0,0 +1,112 @@
/* eslint-disable func-names */
require('./helper');

describe('Partials spec', function () {
beforeEach(function () {
Mustache.clearCache();
});

it('The greater-than operator should expand to the named partial.', function () {
var template = '"{{>text}}"';
var data = {};
var partials = {'text':'from partial'};
var expected = '"from partial"';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});
it('The empty string should be used when the named partial is not found.', function () {
var template = '"{{>text}}"';
var data = {};
var partials = {};
var expected = '""';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});
it('The greater-than operator should operate within the current context.', function () {
var template = '"{{>partial}}"';
var data = {'text':'content'};
var partials = {'partial':'*{{text}}*'};
var expected = '"*content*"';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});
it('The greater-than operator should properly recurse.', function () {
var template = '{{>node}}';
var data = {'content':'X','nodes':[{'content':'Y','nodes':[]}]};
var partials = {'node':'{{content}}<{{#nodes}}{{>node}}{{/nodes}}>'};
var expected = 'X<Y<>>';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});
it('The greater-than operator should not alter surrounding whitespace.', function () {
var template = '| {{>partial}} |';
var data = {};
var partials = {'partial':'\t|\t'};
var expected = '| \t|\t |';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});
it('"\r\n" should be considered a newline for standalone tags.', function () {
var template = '|\r\n{{>partial}}\r\n|';
var data = {};
var partials = {'partial':'>'};
var expected = '|\r\n>|';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});
it('Standalone tags should not require a newline to precede them.', function () {
var template = ' {{>partial}}\n>';
var data = {};
var partials = {'partial':'>\n>'};
var expected = ' >\n >>';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});
it('Superfluous in-tag whitespace should be ignored.', function () {
var template = '|{{> partial }}|';
var data = {'boolean':true};
var partials = {'partial':'[]'};
var expected = '|[]|';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});
it('Each line of the partial should be indented before rendering.', function () {
var template = '\\\n {{>partial}}\n/\n';
var data = {
'content': '<\n->'
};
var partials = {
'partial': '|\n{{{content}}}\n|\n'
};
var expected = '\\\n |\n <\n->\n |\n/\n';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});

it('Standalone tags should not require a newline to follow them.', function () {
var template = '>\n {{>partial}}';
var data = {
};
var partials = {
'partial': '>\n>'
};
var expected = '>\n >\n >';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});

it('Whitespace should be left untouched.', function () {
var template = ' {{data}} {{> partial}}\n';
var data = {
'data': '|'
};
var partials = {
'partial': '>\n>'
};
var expected = ' | >\n>\n';
var renderResult = Mustache.render(template, data, partials);
assert.equal(renderResult, expected);
});
});

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

@@ -18,11 +18,13 @@ describe('Mustache.render', function () {
});

describe('preserve indentation when using partials', function() {
it.only ('should preserve indentation', function() {
var template = 'line1\n bla la \t\r\f foo line2{{>p1}}';

it ('should preserve indentation with whitespaces', function() {
var template = 'a\n {{>p1}}';
var renderResult = Mustache.render(template, {}, {p1: 'l1\nl2'});
assert.equal(renderResult, 'line1\n bla la \t\r\f foo line2l1\n \t\r\f l2');
assert.equal(renderResult, 'a\n l1\n l2');
});

});

describe('custom tags', function () {


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