Index: third_party/handlebar/handlebar.py |
diff --git a/third_party/handlebar/handlebar.py b/third_party/handlebar/handlebar.py |
index 3e7b5a535d334ff3ef267acbbe22570ff6eddff6..c5a2c101629ab0ed9e25444a9d053d941982b7bd 100644 |
--- a/third_party/handlebar/handlebar.py |
+++ b/third_party/handlebar/handlebar.py |
@@ -43,9 +43,6 @@ class CustomContext(object): |
print(Handlebar('hello {{world}}').render(CustomContext()).text) |
""" |
-def _SafeStr(obj): |
- return obj if isinstance(obj, basestring) else str(obj) |
- |
class ParseException(Exception): |
""" Exception thrown while parsing the template. |
""" |
@@ -65,22 +62,24 @@ class StringBuilder(object): |
""" |
def __init__(self): |
self._buf = [] |
- self._length = 0 |
def __len__(self): |
- return self._length |
+ self._Collapse() |
+ return len(self._buf[0]) |
- def append(self, obj): |
- string = _SafeStr(obj) |
+ def append(self, string): |
self._buf.append(string) |
- self._length += len(string) |
def toString(self): |
- return u''.join(self._buf) |
+ self._Collapse() |
+ return self._buf[0] |
def __str__(self): |
return self.toString() |
+ def _Collapse(self): |
+ self._buf = [u''.join(self._buf)] |
+ |
class RenderState(object): |
""" The state of a render call. |
""" |
@@ -110,7 +109,7 @@ class RenderState(object): |
return self |
buf = StringBuilder() |
for message in messages: |
- buf.append(message) |
+ buf.append(str(message)) |
self.errors.append(buf.toString()) |
return self |
@@ -144,16 +143,16 @@ class Identifier(object): |
return self._resolveFromContext(renderState.getFirstContext()) |
resolved = self._resolveFromContexts(renderState.localContexts) |
- if resolved == None: |
+ if resolved is None: |
resolved = self._resolveFromContexts(renderState.globalContexts) |
- if resolved == None: |
+ if resolved is None: |
renderState.addError("Couldn't resolve identifier ", self._path) |
return resolved |
def _resolveFromContexts(self, contexts): |
for context in contexts: |
resolved = self._resolveFromContext(context) |
- if resolved != None: |
+ if resolved is not None: |
return resolved |
return None |
@@ -162,7 +161,7 @@ class Identifier(object): |
for next in self._path: |
# Only require that contexts provide a get method, meaning that callers |
# can provide dict-like contexts (for example, to populate values lazily). |
- if result == None or not getattr(result, "get", None): |
+ if result is None or not getattr(result, "get", None): |
return None |
result = result.get(next) |
return result |
@@ -236,32 +235,26 @@ class InlineNode(DecoratorNode): |
self._content.render(contentRenderState) |
renderState.errors.extend(contentRenderState.errors) |
- |
- for c in contentRenderState.text.toString(): |
- if c != '\n': |
- renderState.text.append(c) |
+ renderState.text.append( |
+ contentRenderState.text.toString().replace('\n', '')) |
class IndentedNode(DecoratorNode): |
def __init__(self, content, indentation): |
DecoratorNode.__init__(self, content) |
- self._indentation = indentation |
+ self._indent_str = ' ' * indentation |
def render(self, renderState): |
contentRenderState = renderState.inSameContext() |
self._content.render(contentRenderState) |
renderState.errors.extend(contentRenderState.errors) |
- |
- self._indent(renderState.text) |
- for i, c in enumerate(contentRenderState.text.toString()): |
- renderState.text.append(c) |
- if c == '\n' and i < len(contentRenderState.text) - 1: |
- self._indent(renderState.text) |
+ renderState.text.append(self._indent_str) |
+ # TODO: this might introduce an extra \n at the end? need test. |
+ renderState.text.append( |
+ contentRenderState.text.toString().replace('\n', |
+ '\n' + self._indent_str)) |
renderState.text.append('\n') |
- def _indent(self, buf): |
- buf.append(' ' * self._indentation) |
- |
class BlockNode(DecoratorNode): |
def __init__(self, content): |
DecoratorNode.__init__(self, content) |
@@ -354,19 +347,13 @@ class EscapedVariableNode(LeafNode): |
def render(self, renderState): |
value = self._id.resolve(renderState) |
- if value != None: |
- self._appendEscapedHtml(renderState.text, _SafeStr(value)) |
- |
- def _appendEscapedHtml(self, escaped, unescaped): |
- for c in unescaped: |
- if c == '<': |
- escaped.append("<") |
- elif c == '>': |
- escaped.append(">") |
- elif c == '&': |
- escaped.append("&") |
- else: |
- escaped.append(c) |
+ if value is None: |
+ return |
+ |
+ string = value if isinstance(value, basestring) else str(value) |
+ renderState.text.append(string.replace('&', '&') |
+ .replace('<', '<') |
+ .replace('>', '>')) |
class UnescapedVariableNode(LeafNode): |
""" {{{foo}}} |
@@ -377,8 +364,10 @@ class UnescapedVariableNode(LeafNode): |
def render(self, renderState): |
value = self._id.resolve(renderState) |
- if value != None: |
- renderState.text.append(value) |
+ if value is None: |
+ return |
+ renderState.text.append( |
+ value if isinstance(value, basestring) else str(value)) |
class SectionNode(DecoratorNode): |
""" {{#foo}} ... {{/}} |
@@ -389,7 +378,7 @@ class SectionNode(DecoratorNode): |
def render(self, renderState): |
value = self._id.resolve(renderState) |
- if value == None: |
+ if value is None: |
return |
if isinstance(value, list): |
@@ -420,7 +409,7 @@ class VertedSectionNode(DecoratorNode): |
renderState.localContexts.pop(0) |
def _VertedSectionNodeShouldRender(value): |
- if value == None: |
+ if value is None: |
return False |
if isinstance(value, bool): |
return value |
@@ -457,8 +446,9 @@ class JsonNode(LeafNode): |
def render(self, renderState): |
value = self._id.resolve(renderState) |
- if value != None: |
- renderState.text.append(json.dumps(value, separators=(',',':'))) |
+ if value is None: |
+ return |
+ renderState.text.append(json.dumps(value, separators=(',',':'))) |
class PartialNode(LeafNode): |
""" {{+foo}} |
@@ -549,7 +539,7 @@ class TokenStream(object): |
self.advance() |
def hasNext(self): |
- return self.nextToken != None |
+ return self.nextToken is not None |
def advance(self): |
if self.nextContents == '\n': |