reflected_mustache 1.0.11 reflected_mustache: ^1.0.11 copied to clipboard
Mustache template library
Mustache templates - Reflected-Version #
This is a clone of Greg Lowes mustace-package
This 'reflected'-package uses reflection instead of mirrors wich makes it Dart 2.x/Browser compatible #
Example #
Live on http://reflected_mustache.example.mikemitterer.at/
Source on GitHub
Mustache / Dart #
A Dart library to parse and render mustache templates.
See the mustache manual for detailed usage information.
This library passes all mustache specification tests.
Example usage - browser #
import 'dart:html' as dom;
import 'package:reflected_mustache/mustache.dart';
import 'main.reflectable.dart';
@mustache
class Version {
final int major;
final int minor;
Version(this.major, this.minor);
}
@mustache
class DartLang {
final String name;
final Version version;
final String message;
DartLang(this.name, this.version, this.message);
}
void main() {
initializeReflectable();
final Template template = new Template(
"""
<div>
Language: {{name}}<br>
Version: {{version.major}}.{{version.minor}}<br>
Comment: {{message}}
</div>
""".trim(), lenient: false,htmlEscapeValues: false);
final DartLang language = new DartLang("Dart",new Version(1,13),"Your Dart app is running.");
final String content = template.renderString(language);
final dom.Element child = new dom.Element.html(content);
dom.querySelector('#content').append(child);
dom.querySelector("body").classes
.removeWhere((final String selector) => selector == "loading");
}
Example usage - cmdline #
import 'package:mustache/mustache.dart';
main() {
var source = '''
{{# names }}
<div>{{ lastname }}, {{ firstname }}</div>
{{/ names }}
{{^ names }}
<div>No names.</div>
{{/ names }}
{{! I am a comment. }}
''';
var template = new Template(source, name: 'template-filename.html');
var output = template.renderString({'names': [
{'firstname': 'Greg', 'lastname': 'Lowe'},
{'firstname': 'Bob', 'lastname': 'Johnson'}
]});
print(output);
}
A template is parsed when it is created, after parsing it can be rendered any number of times with different values. A TemplateException is thrown if there is a problem parsing or rendering the template.
The Template contstructor allows passing a name, this name will be used in error messages. When working with a number of templates, it is important to pass a name so that the error messages specify which template caused the error.
By default all output from {{variable}}
tags is html escaped, this behaviour can be changed by passing htmlEscapeValues : false to the Template constructor. You can also use a {{{triple mustache}}}
tag, or a unescaped variable tag {{&unescaped}}
, the output from these tags is not escaped.
Reflection #
This library uses reflection
to get runtime type information. This means - no mirrors necessary
For more info check out the reflectable
-package
Differences between strict mode and lenient mode. #
Strict mode (default) #
-
Tag names may only contain the characters a-z, A-Z, 0-9, underscore, period and minus. Other characters in tags will cause a TemplateException to be thrown during parsing.
-
During rendering, if no map key or object member which matches the tag name is found, then a TemplateException will be thrown.
Lenient mode #
- Tag names may use any characters.
- During rendering, if no map key or object member which matches the tag name is found, then silently ignore and output nothing.
Nested paths #
var t = new Template('{{ author.name }}');
var output = template.renderString({'author': {'name': 'Greg Lowe'}});
Partials - example usage #
var partial = new Template('{{ foo }}', name: 'partial');
var resolver = (String name) {
if (name == 'partial-name') { // Name of partial tag.
return partial;
}
};
var t = new Template('{{> partial-name }}', partialResolver: resolver);
var output = t.renderString({'foo': 'bar'}); // bar
Lambdas - example usage #
var t = new Template('{{# foo }}');
var lambda = (_) => 'bar';
t.renderString({'foo': lambda}); // bar
var t = new Template('{{# foo }}hidden{{/ foo }}');
var lambda = (_) => 'shown'};
t.renderString({'foo': lambda); // shown
var t = new Template('{{# foo }}oi{{/ foo }}');
var lambda = (LambdaContext ctx) => '<b>${ctx.renderString().toUpperCase()}</b>';
t.renderString({'foo': lambda}); // <b>OI</b>
var t = new Template('{{# foo }}{{bar}}{{/ foo }}');
var lambda = (LambdaContext ctx) => '<b>${ctx.renderString().toUpperCase()}</b>';
t.renderString({'foo': lambda, 'bar': 'pub'}); // <b>PUB</b>
var t = new Template('{{# foo }}{{bar}}{{/ foo }}');
var lambda = (LambdaContext ctx) => '<b>${ctx.renderString().toUpperCase()}</b>';
t.renderString({'foo': lambda, 'bar': 'pub'}); // <b>PUB</b>
In the following example LambdaContext.renderSource(source)
re-parses the source string in the current context, this is the default behaviour in many mustache implementations. Since re-parsing the content is slow, and often not required, this library makes this step optional.
var t = new Template('{{# foo }}{{bar}}{{/ foo }}');
var lambda = (LambdaContext ctx) => ctx.renderSource(ctx.source + ' {{cmd}}')};
t.renderString({'foo': lambda, 'bar': 'pub', 'cmd': 'build'}); // pub build