Add basic lambda support
diff --git a/lib/template.dart b/lib/template.dart
index aa8a7a8..32736d0 100644
--- a/lib/template.dart
+++ b/lib/template.dart
@@ -95,11 +95,12 @@
_Renderer(this._root,
this._sink,
this._values,
- this._stack,
+ List stack,
this._lenient,
this._htmlEscapeValues,
this._partialResolver,
- this._templateName);
+ this._templateName)
+ : _stack = new List.from(stack);
_Renderer.partial(_Renderer renderer, _Template partial)
: this(partial._root,
@@ -111,6 +112,16 @@
renderer._partialResolver,
renderer._templateName);
+ _Renderer.subtree(_Renderer renderer, _Node node, StringSink sink)
+ : this(node,
+ sink,
+ renderer._values,
+ renderer._stack,
+ renderer._lenient,
+ renderer._htmlEscapeValues,
+ renderer._partialResolver,
+ renderer._templateName);
+
final _Node _root;
final StringSink _sink;
final _values;
@@ -179,7 +190,7 @@
}
return object;
}
-
+
// Returns the property of the given object by name. For a map,
// which contains the key name, this is object[name]. For other
// objects, this is object.name or object.name(). If no property
@@ -213,7 +224,10 @@
}
_renderVariable(node, {bool escape : true}) {
- final value = _resolveValue(node.value);
+ var value = _resolveValue(node.value);
+
+ if (value is Function) value = value('');
+
if (value == _NO_SUCH_PROPERTY) {
if (!_lenient)
throw new MustacheFormatException(
@@ -234,23 +248,41 @@
_stack.removeLast();
}
+ String _renderSubtree(node) {
+ var sink = new StringBuffer();
+ var renderer = new _Renderer.subtree(this, node, sink);
+ renderer.render();
+ return sink.toString();
+ }
+
_renderSection(node) {
- final value = _resolveValue(node.value);
+ var value = _resolveValue(node.value);
+
if (value == null) {
// Do nothing.
+
} else if (value is Iterable) {
value.forEach((v) => _renderSectionWithValue(node, v));
+
} else if (value is Map) {
_renderSectionWithValue(node, value);
+
} else if (value == true) {
_renderSectionWithValue(node, value);
+
} else if (value == false) {
// Do nothing.
+
} else if (value == _NO_SUCH_PROPERTY) {
if (!_lenient)
throw new MustacheFormatException(
'Value was missing, section: ${node.value}',
_templateName, node.line, node.column);
+
+ } else if (value is Function) {
+ var output = _renderSubtree(node);
+ _write(value(output));
+
} else {
throw new MustacheFormatException(
'Invalid value type for section, '
@@ -261,13 +293,17 @@
}
_renderInvSection(node) {
- final value = _resolveValue(node.value);
+ var value = _resolveValue(node.value);
+
if (value == null) {
_renderSectionWithValue(node, null);
+
} else if ((value is Iterable && value.isEmpty) || value == false) {
_renderSectionWithValue(node, value);
+
} else if (value == true || value is Map || value is Iterable) {
// Do nothing.
+
} else if (value == _NO_SUCH_PROPERTY) {
if (_lenient) {
_renderSectionWithValue(node, null);
@@ -276,6 +312,15 @@
'Value was missing, inverse-section: ${node.value}',
_templateName, node.line, node.column);
}
+
+ } else if (value is Function) {
+ var output = _renderSubtree(node);
+ if (value(output) != false) {
+ // FIXME not sure what to output here, result of function or template
+ // output?
+ _write(output);
+ }
+
} else {
throw new MustacheFormatException(
'Invalid value type for inverse section, '
diff --git a/test/mustache_test.dart b/test/mustache_test.dart
index 94dae11..55df9da 100644
--- a/test/mustache_test.dart
+++ b/test/mustache_test.dart
@@ -311,6 +311,41 @@
});
+ group('Lambdas', () {
+
+ _lambdaTest({template, lambda, output}) =>
+ expect(parse(template).renderString({'lambda': lambda}), equals(output));
+
+ test('basic', () {
+ _lambdaTest(
+ template: 'Hello, {{lambda}}!',
+ lambda: (_) => 'world',
+ output: 'Hello, world!');
+ });
+
+ test('escaping', () {
+ _lambdaTest(
+ template: '<{{lambda}}{{{lambda}}}',
+ lambda: (_) => '>',
+ output: '<>>');
+ });
+
+ test('sections', () {
+ _lambdaTest(
+ template: '{{#lambda}}FILE{{/lambda}} != {{#lambda}}LINE{{/lambda}}',
+ lambda: (s) => '__${s}__',
+ output: '__FILE__ != __LINE__');
+ });
+
+ test('inverted sections truthy', () {
+ var template = '<{{^lambda}}{{static}}{{/lambda}}>';
+ var values = {'lambda': (_) => false, 'static': 'static'};
+ var output = '<>';
+ expect(parse(template).renderString(values), equals(output));
+ });
+
+ });
+
group('Other', () {
test('Standalone line', () {
var val = parse('|\n{{#bob}}\n{{/bob}}\n|').renderString({'bob': []});