Update docs, fix comments
diff --git a/README.md b/README.md
index 0ebcd9c..04561fc 100644
--- a/README.md
+++ b/README.md
@@ -2,15 +2,55 @@
A Dart library to parse and render [mustache templates](http://mustache.github.com/mustache.5.html).
-# Example
+## Example
```dart
-import 'package:mustache/mustache.dart';
+ import 'package:mustache/mustache.dart' as mustache;
-main() {
- var source = '{{#section}}_{{var}}_{{/section}}';
- var values = {"section": {"var": "bob"}};
- var template = parse(source);
- var output = template.render(values);
- print(output);
-}
+ main() {
+ var source = '{{#names}}<div>{{lastname}}, {{firstname}}</div>{{/names}}';
+ var template = mustache.parse(source);
+ var output = template.render({'names': [
+ {'fistname': 'Greg', 'lastname': 'Lowe'},
+ {'fistname': 'Bob', 'lastname': 'Johnson'}
+ ]});
+ print(output);
+ }
```
+
+## API
+
+```dart
+
+Template parse(String source, {bool lenient : false});
+
+abstract class Template {
+ String render(values, {bool lenient : false});
+}
+
+```
+
+Once a template has been created it can be rendered any number of times.
+
+Both parse and render throw a FormatException if there is a problem with the template or rendering the values.
+
+When lenient mode is enabled tag names may use any characters, otherwise only a-z, A-Z, 0-9, underscore and minus. Lenient mode will also silently ignore nulls passed as values.
+
+
+## Supported
+```
+ Variables {{var-name}}
+ Sections {{#section}}Blah{{/section}}
+ Inverse sections {{^section}}Blah{{/section}}
+ Comments {{! Not output. }}
+```
+See the [mustache templates tutorial](http://mustache.github.com/mustache.5.html) for more information.
+
+## To do
+
+Escape tags {{{ ... }}}, and {{& ... }}
+Partial tags {{>partial}}
+Functions as values
+And maybe later:
+ Incremental parser, and renderer (i.e. Stream based)
+ Allow the incremental renderer to handle values which are Futures and Streams.
+
diff --git a/lib/mustache.dart b/lib/mustache.dart
index cdd604b..ff6dac7 100644
--- a/lib/mustache.dart
+++ b/lib/mustache.dart
@@ -4,23 +4,26 @@
part 'scanner.dart';
part 'template.dart';
-/// Mustache docs http://mustache.github.com/mustache.5.html
+/// [Mustache template documentation](http://mustache.github.com/mustache.5.html)
-/// Returns a [Template] which can be used to render the template with substituted
-/// values.
+/// Returns a [Template] which can be used to render the mustache template
+/// with substituted values.
+/// Tag names may only contain characters a-z, A-Z, 0-9, underscore, and minus,
+/// unless lenient mode is specified.
/// Throws [FormatException] if the syntax of the source is invalid.
Template parse(String source,
{bool lenient : false}) => _parse(source, lenient: lenient);
-/// A Template can be used multiple times to [render] content with different values.
+/// A Template can be rendered multiple times with different values.
abstract class Template {
/// [values] can be a combination of Map, List, String. Any non-String object
- /// will be converted using toString().
+ /// will be converted using toString(). Null values will cause a
+ /// FormatException, unless lenient module is enabled.
String render(values, {bool lenient : false});
}
-/// MustacheFormatException can be used to obtain the line and column numbers
-/// of the token which caused [parse] to fail.
+/// MustacheFormatException is used to obtain the line and column numbers
+/// of the token which caused parse or render to fail.
class MustacheFormatException implements FormatException {
final String message;
diff --git a/lib/scanner.dart b/lib/scanner.dart
index 023d468..0cd1c42 100644
--- a/lib/scanner.dart
+++ b/lib/scanner.dart
@@ -137,7 +137,7 @@
// Comment {{! ... }}
case _EXCLAIM:
_read();
- _addStringToken(_COMMENT);
+ _addStringToken(_COMMENT); //FIXME hmmm need to think about escaping rules here.
break;
// Partial {{> ... }}
diff --git a/lib/template.dart b/lib/template.dart
index 31102ee..4e9c8f3 100644
--- a/lib/template.dart
+++ b/lib/template.dart
@@ -34,6 +34,9 @@
stack.removeLast();
+ } else if (t.type == _COMMENT) {
+ // Do nothing
+
} else {
throw new UnimplementedError();
}
@@ -93,6 +96,8 @@
case _OPEN_INV_SECTION:
_renderInvSection(node);
break;
+ case _COMMENT:
+ break; // Do nothing.
default:
throw new UnimplementedError();
}
diff --git a/test/mustache_test.dart b/test/mustache_test.dart
index b284efa..bfe867d 100644
--- a/test/mustache_test.dart
+++ b/test/mustache_test.dart
@@ -11,6 +11,17 @@
const VALUE_NULL = 'Value was null or missing';
main() {
+ group('Basic', () {
+ test('Variable', () {
+ var output = parse('_{{var}}_')
+ .render({"var": "bob"});
+ expect(output, equals('_bob_'));
+ });
+ test('Comment', () {
+ var output = parse('_{{! i am a comment ! }}_').render({});
+ expect(output, equals('__'));
+ });
+ });
group('Section', () {
test('Map', () {
var output = parse('{{#section}}_{{var}}_{{/section}}')