Added more methods to LambdaContext
diff --git a/lib/mustache.dart b/lib/mustache.dart
index 197b89a..ba7c513 100644
--- a/lib/mustache.dart
+++ b/lib/mustache.dart
@@ -61,28 +61,29 @@
abstract class LambdaContext {
/// Render the current section tag in the current context and return the
- /// result as a string.
- String renderString();
+ /// result as a string. If provided, value will be added to the top of the
+ /// context's stack.
+ String renderString({Object value});
- /// Render and directly output the current section tag.
- //TODO note in variable case need to capture output in a string buffer and escape.
- //void render();
+ /// Render and directly output the current section tag. If provided, value
+ /// will be added to the top of the context's stack.
+ void render({Object value});
- /// Output a string.
- //TODO note in variable case need to capture output in a string buffer and escape.
- //void write(Object object);
+ /// Output a string. The output will not be html escaped, and will be written
+ /// before the output returned from the lambda.
+ void write(Object object);
/// Get the unevaluated template source for the current section tag.
String get source;
- /// Evaluate the string as a mustache template using the current context.
- String renderSource(String source);
+ /// Evaluate the string as a mustache template using the current context. If
+ /// provided, value will be added to the top of the context's stack.
+ String renderSource(String source, {Object value});
- /// Lookup the value of a variable in the current context.
+ /// Lookup the value of a variable in the current context.
Object lookup(String variableName);
}
-
const MustacheMirrorsUsedAnnotation mustache = const MustacheMirrorsUsedAnnotation();
class MustacheMirrorsUsedAnnotation {
diff --git a/lib/src/lambda_context.dart b/lib/src/lambda_context.dart
index 2ed1e47..2d634af 100644
--- a/lib/src/lambda_context.dart
+++ b/lib/src/lambda_context.dart
@@ -26,29 +26,34 @@
/// Render the current section tag in the current context and return the
/// result as a string.
- String renderString() {
+ String renderString({Object value}) {
+ _checkClosed();
if (_node is! _SectionNode) _error(
'LambdaContext.renderString() can only be called on section tags.');
- _checkClosed();
var sink = new StringBuffer();
- var ctx = new _RenderContext.subtree(_context, sink);
- _SectionNode section = _node;
- _renderWithContext(ctx, section.children);
+ _renderSubtree(sink, value);
return sink.toString();
}
- //FIXME Currently only return values are supported.
- /// Render and directly output the current section tag.
-// void render() {
-// _checkClosed();
-// }
+ void _renderSubtree(StringSink sink, Object value) {
+ var ctx = new _RenderContext.subtree(_context, sink);
+ _SectionNode section = _node;
+ if (value != null) ctx.push(value);
+ _renderWithContext(ctx, section.children);
+ }
+
+ void render({Object value}) {
+ _checkClosed();
+ if (_node is! _SectionNode) _error(
+ 'LambdaContext.render() can only be called on section tags.');
+ _renderSubtree(_context._sink, value);
+ }
- //FIXME Currently only return values are supported.
- /// Output a string.
-// void write(Object object) {
-// _checkClosed();
-// }
-
+ void write(Object object) {
+ _checkClosed();
+ _context.write(object);
+ }
+
/// Get the unevaluated template source for the current section tag.
String get source {
_checkClosed();
@@ -69,7 +74,7 @@
}
/// Evaluate the string as a mustache template using the current context.
- String renderSource(String source) {
+ String renderSource(String source, {Object value}) {
_checkClosed();
var sink = new StringBuffer();
@@ -92,6 +97,7 @@
sink,
delimiters);
+ if (value != null) ctx.push(value);
_renderWithContext(ctx, nodes);
return sink.toString();
diff --git a/lib/src/node.dart b/lib/src/node.dart
index edd7b4e..5140574 100644
--- a/lib/src/node.dart
+++ b/lib/src/node.dart
@@ -88,7 +88,7 @@
var output = !escape || !ctx.htmlEscapeValues
? valueString
: _htmlEscape(valueString);
- ctx.write(output);
+ if (output != null) ctx.write(output);
}
}
@@ -169,7 +169,7 @@
var context = new _LambdaContext(this, renderer, isSection: true);
var output = value(context);
context.close();
- renderer.write(output);
+ if (output != null) renderer.write(output);
} else {
throw renderer.error('Invalid value type for section, '
@@ -210,9 +210,9 @@
}
void _renderWithValue(_RenderContext ctx, value) {
- ctx.pushValue(value);
+ ctx.push(value);
children.forEach((n) => n.render(ctx));
- ctx.popValue();
+ ctx.pop();
}
}
diff --git a/lib/src/render_context.dart b/lib/src/render_context.dart
index 4f1c8f7..c114380 100644
--- a/lib/src/render_context.dart
+++ b/lib/src/render_context.dart
@@ -61,9 +61,9 @@
final String indent;
final String source;
- void pushValue(value) => _stack.add(value);
+ void push(value) => _stack.add(value);
- Object popValue() => _stack.removeLast();
+ Object pop() => _stack.removeLast();
write(Object output) => _sink.write(output.toString());
diff --git a/test/mustache_test.dart b/test/mustache_test.dart
index f0782f4..055f4fe 100644
--- a/test/mustache_test.dart
+++ b/test/mustache_test.dart
@@ -593,6 +593,65 @@
expect(val, equals('(It worked!)'));
});
});
+
+ group('Lambda context', () {
+
+ test("LambdaContext write", () {
+ var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+ var values = {'markdown': (ctx) {
+ ctx.write('foo');
+ }};
+ var output = '<foo>';
+ expect(parse(template).renderString(values), equals(output));
+ });
+
+ test("LambdaContext render", () {
+ var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+ var values = {'content': 'bar', 'markdown': (ctx) {
+ ctx.render();
+ }};
+ var output = '<bar>';
+ expect(parse(template).renderString(values), equals(output));
+ });
+
+ test("LambdaContext render with value", () {
+ var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+ var values = {'markdown': (LambdaContext ctx) {
+ ctx.render(value: {'content': 'oi!'});
+ }};
+ var output = '<oi!>';
+ expect(parse(template).renderString(values), equals(output));
+ });
+
+ test("LambdaContext renderString with value", () {
+ var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+ var values = {'markdown': (LambdaContext ctx) {
+ return ctx.renderString(value: {'content': 'oi!'});
+ }};
+ var output = '<oi!>';
+ expect(parse(template).renderString(values), equals(output));
+ });
+
+ test("LambdaContext write and return", () {
+ var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+ var values = {'markdown': (LambdaContext ctx) {
+ ctx.write('foo');
+ return 'bar';
+ }};
+ var output = '<foobar>';
+ expect(parse(template).renderString(values), equals(output));
+ });
+
+ test("LambdaContext renderSource with value", () {
+ var template = '<{{#markdown}}{{content}}{{/markdown}}>';
+ var values = {'markdown': (LambdaContext ctx) {
+ return ctx.renderSource(ctx.source, value: {'content': 'oi!'});
+ }};
+ var output = '<oi!>';
+ expect(parse(template).renderString(values), equals(output));
+ });
+
+ });
}
renderFail(source, values) {