// TODO(stuartmorgan): Remove this. See https://github.com/flutter/flutter/issues/174722. // ignore_for_file: public_member_api_docs import '../mustache.dart' as m; import 'node.dart'; import 'parser.dart' as parser; import 'renderer.dart'; import 'template_exception.dart'; /// Passed as an argument to a mustache lambda function. class LambdaContext implements m.LambdaContext { LambdaContext(this._node, this._renderer); final Node _node; final Renderer _renderer; bool _closed = false; void close() { _closed = true; } void _checkClosed() { if (_closed) { throw _error('LambdaContext accessed outside of callback.'); } } TemplateException _error(String msg) { return TemplateException( msg, _renderer.templateName, _renderer.source, _node.start, ); } @override String renderString({Object? value}) { _checkClosed(); if (_node is! SectionNode) { // TODO(stuartmorgan): Fix the lack of `throw` here, which looks like a // bug in the original code. _error( 'LambdaContext.renderString() can only be called on section tags.', ); } final StringBuffer sink = StringBuffer(); _renderSubtree(sink, value); return sink.toString(); } void _renderSubtree(StringSink sink, Object? value) { final Renderer renderer = Renderer.subtree(_renderer, sink); final SectionNode section = _node as SectionNode; if (value != null) { renderer.push(value); } renderer.render(section.children); } @override void render({Object? value}) { _checkClosed(); if (_node is! SectionNode) { // TODO(stuartmorgan): Fix the lack of `throw` here, which looks like a // bug in the original code. _error('LambdaContext.render() can only be called on section tags.'); } _renderSubtree(_renderer.sink, value); } @override void write(Object object) { _checkClosed(); _renderer.write(object); } @override String get source { _checkClosed(); if (_node is! SectionNode) { return ''; } final SectionNode node = _node; final List nodes = node.children; if (nodes.isEmpty) { return ''; } if (nodes.length == 1 && nodes.first is TextNode) { return (nodes.single as TextNode).text; } return _renderer.source.substring(node.contentStart, node.contentEnd); } @override String renderSource(String source, {Object? value}) { _checkClosed(); final StringBuffer sink = StringBuffer(); // Lambdas used for sections should parse with the current delimiters. String delimiters = '{{ }}'; if (_node is SectionNode) { final SectionNode node = _node; delimiters = node.delimiters; } final List nodes = parser.parse( source, _renderer.lenient, _renderer.templateName, delimiters, ); final Renderer renderer = Renderer.lambda( _renderer, source, _renderer.indent, sink, ); if (value != null) { renderer.push(value); } renderer.render(nodes); return sink.toString(); } @override Object? lookup(String variableName) { _checkClosed(); return _renderer.resolveValue(variableName); } }