Add mirrors support back
diff --git a/lib/mustache.dart b/lib/mustache.dart
index 7a5b0d2..8ac1af6 100644
--- a/lib/mustache.dart
+++ b/lib/mustache.dart
@@ -1,12 +1,13 @@
library mustache;
-part 'char_reader.dart';
-part 'scanner.dart';
-part 'template.dart';
+import 'dart:mirrors';
+
+part 'src/char_reader.dart';
+part 'src/scanner.dart';
+part 'src/template.dart';
/// [Mustache template documentation](http://mustache.github.com/mustache.5.html)
-
/// Use new Template(source) instead.
@deprecated
Template parse(String source, {bool lenient : false})
@@ -25,8 +26,7 @@
{bool lenient,
bool htmlEscapeValues,
String name,
- PartialResolver partialResolver,
- PropertyResolver propertyResolver}) = _Template.source;
+ PartialResolver partialResolver}) = _Template.source;
/// [values] can be a combination of Map, List, String. Any non-String object
/// will be converted using toString(). Null values will cause a
@@ -86,13 +86,3 @@
//TODO does this require some sort of context to find partials nested in subdirs?
typedef Template PartialResolver(String templateName);
-//Allows pluggable property lookup. This is so code using mirrors can be
-// plugged in without requiring the mirrors dependency in the core library.
-typedef Object PropertyResolver(Object obj, String name);
-
-// Useful for handing partials
-abstract class TemplateRenderer {
- String renderString(String templateName, values);
- void render(String templateName, values, StringSink sink);
-}
-
diff --git a/lib/char_reader.dart b/lib/src/char_reader.dart
similarity index 100%
rename from lib/char_reader.dart
rename to lib/src/char_reader.dart
diff --git a/lib/scanner.dart b/lib/src/scanner.dart
similarity index 95%
rename from lib/scanner.dart
rename to lib/src/scanner.dart
index b144b3a..32b03dc 100644
--- a/lib/scanner.dart
+++ b/lib/src/scanner.dart
@@ -1,9 +1,5 @@
part of mustache;
-//FIXME Temporarily made public for testing.
-//List<_Token> scan(String source, bool lenient) => _scan(source, lenient);
-//List<_Token> trim(List<_Token> tokens) => _trim(tokens);
-
List<_Token> _scan(String source, bool lenient) => _trim(new _Scanner(source).scan());
const int _TEXT = 1;
@@ -18,7 +14,7 @@
const int _LINE_END = 10; // Should be filtered out, before returned by scan.
//FIXME make private
-tokenTypeString(int type) => [
+_tokenTypeString(int type) => [
'?',
'Text',
'Var',
@@ -137,7 +133,7 @@
final String value;
final int line;
final int column;
- toString() => "${tokenTypeString(type)}: \"${value.replaceAll('\n', '\\n')}\" $line:$column";
+ toString() => "${_tokenTypeString(type)}: \"${value.replaceAll('\n', '\\n')}\" $line:$column";
}
class _Scanner {
diff --git a/lib/template.dart b/lib/src/template.dart
similarity index 84%
rename from lib/template.dart
rename to lib/src/template.dart
index cce5c2e..18b6a20 100644
--- a/lib/template.dart
+++ b/lib/src/template.dart
@@ -1,6 +1,6 @@
part of mustache;
-const Object _NO_SUCH_PROPERTY = const Object();
+const Object _noSuchProperty = const Object();
final RegExp _validTag = new RegExp(r'^[0-9a-zA-Z\_\-\.]+$');
final RegExp _integerTag = new RegExp(r'^[0-9]+$');
@@ -64,34 +64,29 @@
{bool lenient: false,
bool htmlEscapeValues : true,
String name,
- PartialResolver partialResolver,
- PropertyResolver propertyResolver})
+ PartialResolver partialResolver})
: _root = _parse(source, lenient, name),
_lenient = lenient,
_htmlEscapeValues = htmlEscapeValues,
_name = name,
- _partialResolver = partialResolver,
- _propertyResolver = propertyResolver;
+ _partialResolver = partialResolver;
// TODO share impl with _Template.source;
_Template.root(this._root,
{bool lenient: false,
bool htmlEscapeValues : true,
String name,
- PartialResolver partialResolver,
- PropertyResolver propertyResolver})
+ PartialResolver partialResolver})
: _lenient = lenient,
_htmlEscapeValues = htmlEscapeValues,
_name = name,
- _partialResolver = partialResolver,
- _propertyResolver = propertyResolver;
+ _partialResolver = partialResolver;
final _Node _root;
final bool _lenient;
final bool _htmlEscapeValues;
final String _name;
final PartialResolver _partialResolver;
- final PropertyResolver _propertyResolver;
String renderString(values) {
var buf = new StringBuffer();
@@ -101,7 +96,7 @@
void render(values, StringSink sink) {
var renderer = new _Renderer(_root, sink, values, [values],
- _lenient, _htmlEscapeValues, _partialResolver, _propertyResolver, _name);
+ _lenient, _htmlEscapeValues, _partialResolver, _name);
renderer.render();
}
}
@@ -116,7 +111,6 @@
this._lenient,
this._htmlEscapeValues,
this._partialResolver,
- this._propertyResolver,
this._templateName)
: _stack = new List.from(stack);
@@ -128,7 +122,6 @@
renderer._lenient,
renderer._htmlEscapeValues,
renderer._partialResolver,
- renderer._propertyResolver,
renderer._templateName);
_Renderer.subtree(_Renderer renderer, _Node node, StringSink sink)
@@ -139,7 +132,6 @@
renderer._lenient,
renderer._htmlEscapeValues,
renderer._partialResolver,
- renderer._propertyResolver,
renderer._templateName);
final _Node _root;
@@ -149,7 +141,6 @@
final bool _lenient;
final bool _htmlEscapeValues;
final PartialResolver _partialResolver;
- final PropertyResolver _propertyResolver;
final String _templateName;
void render() {
@@ -196,16 +187,16 @@
return _stack.last;
}
var parts = name.split('.');
- var object = _NO_SUCH_PROPERTY;
+ var object = _noSuchProperty;
for (var o in _stack.reversed) {
object = _getNamedProperty(o, parts[0]);
- if (object != _NO_SUCH_PROPERTY) {
+ if (object != _noSuchProperty) {
break;
}
}
for (int i = 1; i < parts.length; i++) {
- if (object == null || object == _NO_SUCH_PROPERTY) {
- return _NO_SUCH_PROPERTY;
+ if (object == null || object == _noSuchProperty) {
+ return _noSuchProperty;
}
object = _getNamedProperty(object, parts[i]);
}
@@ -215,11 +206,9 @@
// 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
- // by the given name exists, this method returns _NO_SUCH_PROPERTY.
+ // by the given name exists, this method returns noSuchProperty.
_getNamedProperty(object, name) {
- if (_propertyResolver != null) return _propertyResolver(object, name);
-
var property = null;
if (object is Map && object.containsKey(name))
return object[name];
@@ -228,23 +217,22 @@
return object[int.parse(name)];
if (_lenient && !_validTag.hasMatch(name))
- return _NO_SUCH_PROPERTY;
+ return _noSuchProperty;
-// Move mirrors code into another library.
-// var instance = reflect(object);
-// var field = instance.type.instanceMembers[new Symbol(name)];
-// if (field == null) return _NO_SUCH_PROPERTY;
-//
-// var invocation = null;
-// if ((field is VariableMirror) || ((field is MethodMirror) && (field.isGetter))) {
-// invocation = instance.getField(field.simpleName);
-// } else if ((field is MethodMirror) && (field.parameters.length == 0)) {
-// invocation = instance.invoke(field.simpleName, []);
-// }
-// if (invocation == null) {
-// return _NO_SUCH_PROPERTY;
-// }
-// return invocation.reflectee;
+ var instance = reflect(object);
+ var field = instance.type.instanceMembers[new Symbol(name)];
+ if (field == null) return _noSuchProperty;
+
+ var invocation = null;
+ if ((field is VariableMirror) || ((field is MethodMirror) && (field.isGetter))) {
+ invocation = instance.getField(field.simpleName);
+ } else if ((field is MethodMirror) && (field.parameters.length == 0)) {
+ invocation = instance.invoke(field.simpleName, []);
+ }
+ if (invocation == null) {
+ return _noSuchProperty;
+ }
+ return invocation.reflectee;
}
_renderVariable(node, {bool escape : true}) {
@@ -252,7 +240,7 @@
if (value is Function) value = value('');
- if (value == _NO_SUCH_PROPERTY) {
+ if (value == _noSuchProperty) {
if (!_lenient)
throw new TemplateException(
'Value was missing, variable: ${node.value}',
@@ -297,7 +285,7 @@
} else if (value == false) {
// Do nothing.
- } else if (value == _NO_SUCH_PROPERTY) {
+ } else if (value == _noSuchProperty) {
if (!_lenient)
throw new TemplateException(
'Value was missing, section: ${node.value}',
@@ -328,7 +316,7 @@
} else if (value == true || value is Map || value is Iterable) {
// Do nothing.
- } else if (value == _NO_SUCH_PROPERTY) {
+ } else if (value == _noSuchProperty) {
if (_lenient) {
_renderSectionWithValue(node, null);
} else {
@@ -422,5 +410,5 @@
final int line;
final int column;
final List<_Node> children = new List<_Node>();
- String toString() => '_Node: ${tokenTypeString(type)}';
+ String toString() => '_Node: ${_tokenTypeString(type)}';
}