Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(251)

Side by Side Diff: third_party/handlebar/handlebar.py

Issue 10836212: Extensions Docs Server: Handlebar handles line breaks in partials (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/handlebar/README.chromium ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2012 Benjamin Kalman 1 # Copyright 2012 Benjamin Kalman
2 # 2 #
3 # Licensed under the Apache License, Version 2.0 (the "License"); 3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License. 4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at 5 # You may obtain a copy of the License at
6 # 6 #
7 # http://www.apache.org/licenses/LICENSE-2.0 7 # http://www.apache.org/licenses/LICENSE-2.0
8 # 8 #
9 # Unless required by applicable law or agreed to in writing, software 9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS, 10 # distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 26 matching lines...) Expand all
37 37
38 class CustomContext(object): 38 class CustomContext(object):
39 def get(self, key): 39 def get(self, key):
40 return 10 40 return 10
41 41
42 # Any time {{ }} is used, will fill it with 10. 42 # Any time {{ }} is used, will fill it with 10.
43 print(Handlebar('hello {{world}}').render(CustomContext()).text) 43 print(Handlebar('hello {{world}}').render(CustomContext()).text)
44 """ 44 """
45 45
46 def _SafeStr(obj): 46 def _SafeStr(obj):
47 return obj if (type(obj) in [str, unicode]) else str(obj) 47 return obj if isinstance(obj, basestring) else str(obj)
48 48
49 class ParseException(Exception): 49 class ParseException(Exception):
50 """ Exception thrown while parsing the template. 50 """ Exception thrown while parsing the template.
51 """ 51 """
52 def __init__(self, error, line): 52 def __init__(self, error, line):
53 Exception.__init__(self, "%s (line %s)" % (error, line.number)) 53 Exception.__init__(self, "%s (line %s)" % (error, line.number))
54 54
55 class RenderResult(object): 55 class RenderResult(object):
56 """ Result of a render operation. 56 """ Result of a render operation.
57 """ 57 """
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 """ 385 """
386 def __init__(self, id, content): 386 def __init__(self, id, content):
387 DecoratorNode.__init__(self, content) 387 DecoratorNode.__init__(self, content)
388 self._id = id 388 self._id = id
389 389
390 def render(self, renderState): 390 def render(self, renderState):
391 value = self._id.resolve(renderState) 391 value = self._id.resolve(renderState)
392 if value == None: 392 if value == None:
393 return 393 return
394 394
395 type_ = type(value) 395 if isinstance(value, list):
396 if type_ == list:
397 for item in value: 396 for item in value:
398 renderState.localContexts.insert(0, item) 397 renderState.localContexts.insert(0, item)
399 self._content.render(renderState) 398 self._content.render(renderState)
400 renderState.localContexts.pop(0) 399 renderState.localContexts.pop(0)
401 elif type_ == dict: 400 elif isinstance(value, dict):
402 renderState.localContexts.insert(0, value) 401 renderState.localContexts.insert(0, value)
403 self._content.render(renderState) 402 self._content.render(renderState)
404 renderState.localContexts.pop(0) 403 renderState.localContexts.pop(0)
405 else: 404 else:
406 renderState.addError("{{#", self._id, 405 renderState.addError("{{#", self._id,
407 "}} cannot be rendered with a ", type_) 406 "}} cannot be rendered with a ", type(value))
408 407
409 class VertedSectionNode(DecoratorNode): 408 class VertedSectionNode(DecoratorNode):
410 """ {{?foo}} ... {{/}} 409 """ {{?foo}} ... {{/}}
411 """ 410 """
412 def __init__(self, id, content): 411 def __init__(self, id, content):
413 DecoratorNode.__init__(self, content) 412 DecoratorNode.__init__(self, content)
414 self._id = id 413 self._id = id
415 414
416 def render(self, renderState): 415 def render(self, renderState):
417 value = self._id.resolve(renderState.inSameContext().disableErrors()) 416 value = self._id.resolve(renderState.inSameContext().disableErrors())
418 if _VertedSectionNodeShouldRender(value): 417 if _VertedSectionNodeShouldRender(value):
419 renderState.localContexts.insert(0, value) 418 renderState.localContexts.insert(0, value)
420 self._content.render(renderState) 419 self._content.render(renderState)
421 renderState.localContexts.pop(0) 420 renderState.localContexts.pop(0)
422 421
423 def _VertedSectionNodeShouldRender(value): 422 def _VertedSectionNodeShouldRender(value):
424 if value == None: 423 if value == None:
425 return False 424 return False
426 type_ = type(value) 425 if isinstance(value, bool):
427 if type_ == bool:
428 return value 426 return value
429 if type_ in [int, float]: 427 if (isinstance(value, int) or
428 isinstance(value, long) or
429 isinstance(value, float)):
430 return True 430 return True
431 if type_ in [str, unicode]: 431 if isinstance(value, basestring):
432 return True 432 return True
433 if type_ == list: 433 if isinstance(value, list):
434 return len(value) > 0 434 return len(value) > 0
435 if type_ == dict: 435 if isinstance(value, dict):
436 return True 436 return True
437 raise TypeError("Unhandled type: " + str(type_)) 437 raise TypeError("Unhandled type %s" % type(value))
438 438
439 class InvertedSectionNode(DecoratorNode): 439 class InvertedSectionNode(DecoratorNode):
440 """ {{^foo}} ... {{/}} 440 """ {{^foo}} ... {{/}}
441 """ 441 """
442 def __init__(self, id, content): 442 def __init__(self, id, content):
443 DecoratorNode.__init__(self, content) 443 DecoratorNode.__init__(self, content)
444 self._id = id 444 self._id = id
445 445
446 def render(self, renderState): 446 def render(self, renderState):
447 value = self._id.resolve(renderState.inSameContext().disableErrors()) 447 value = self._id.resolve(renderState.inSameContext().disableErrors())
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 return self.advance() 581 return self.advance()
582 582
583 def advanceOverNextString(self, excluded=''): 583 def advanceOverNextString(self, excluded=''):
584 buf = StringBuilder() 584 buf = StringBuilder()
585 while self.nextToken == Token.CHARACTER and \ 585 while self.nextToken == Token.CHARACTER and \
586 excluded.find(self.nextContents) == -1: 586 excluded.find(self.nextContents) == -1:
587 buf.append(self.nextContents) 587 buf.append(self.nextContents)
588 self.advance() 588 self.advance()
589 return buf.toString() 589 return buf.toString()
590 590
591 def advanceToNextWhitespace(self):
592 return self.advanceOverNextString(excluded=' \n\r\t')
593
594 def skipWhitespace(self):
595 while len(self.nextContents) > 0 and \
596 ' \n\r\t'.find(self.nextContents) >= 0:
597 self.advance()
598
591 class Handlebar(object): 599 class Handlebar(object):
592 """ A handlebar template. 600 """ A handlebar template.
593 """ 601 """
594 def __init__(self, template): 602 def __init__(self, template):
595 self.source = template 603 self.source = template
596 tokens = TokenStream(template) 604 tokens = TokenStream(template)
597 self._topNode = self._parseSection(tokens) 605 self._topNode = self._parseSection(tokens)
598 if not self._topNode: 606 if not self._topNode:
599 raise ParseException("Template is empty", tokens.nextLine) 607 raise ParseException("Template is empty", tokens.nextLine)
600 if tokens.hasNext(): 608 if tokens.hasNext():
(...skipping 12 matching lines...) Expand all
613 startLine = tokens.nextLine 621 startLine = tokens.nextLine
614 string = tokens.advanceOverNextString() 622 string = tokens.advanceOverNextString()
615 nodes.append(StringNode(string, startLine, tokens.nextLine)) 623 nodes.append(StringNode(string, startLine, tokens.nextLine))
616 elif token == Token.OPEN_VARIABLE or \ 624 elif token == Token.OPEN_VARIABLE or \
617 token == Token.OPEN_UNESCAPED_VARIABLE or \ 625 token == Token.OPEN_UNESCAPED_VARIABLE or \
618 token == Token.OPEN_START_JSON: 626 token == Token.OPEN_START_JSON:
619 id = self._openSectionOrTag(tokens) 627 id = self._openSectionOrTag(tokens)
620 nodes.append(token.clazz(id, tokens.nextLine)) 628 nodes.append(token.clazz(id, tokens.nextLine))
621 elif token == Token.OPEN_START_PARTIAL: 629 elif token == Token.OPEN_START_PARTIAL:
622 tokens.advance() 630 tokens.advance()
623 id = Identifier(tokens.advanceOverNextString(excluded=' '), 631 id = Identifier(tokens.advanceToNextWhitespace(),
624 tokens.nextLine) 632 tokens.nextLine)
625 partialNode = PartialNode(id, tokens.nextLine) 633 partialNode = PartialNode(id, tokens.nextLine)
626 634
627 while tokens.nextToken == Token.CHARACTER: 635 while tokens.nextToken == Token.CHARACTER:
628 tokens.advance() 636 tokens.skipWhitespace()
629 key = tokens.advanceOverNextString(excluded=':') 637 key = tokens.advanceOverNextString(excluded=':')
630 tokens.advance() 638 tokens.advance()
631 partialNode.addArgument( 639 partialNode.addArgument(
632 key, 640 key,
633 Identifier(tokens.advanceOverNextString(excluded=' '), 641 Identifier(tokens.advanceToNextWhitespace(),
634 tokens.nextLine)) 642 tokens.nextLine))
635 643
636 tokens.advanceOver(Token.CLOSE_MUSTACHE) 644 tokens.advanceOver(Token.CLOSE_MUSTACHE)
637 nodes.append(partialNode) 645 nodes.append(partialNode)
638 elif token == Token.OPEN_START_SECTION: 646 elif token == Token.OPEN_START_SECTION:
639 id = self._openSectionOrTag(tokens) 647 id = self._openSectionOrTag(tokens)
640 section = self._parseSection(tokens) 648 section = self._parseSection(tokens)
641 self._closeSection(tokens, id) 649 self._closeSection(tokens, id)
642 if section: 650 if section:
643 nodes.append(SectionNode(id, section)) 651 nodes.append(SectionNode(id, section))
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
739 def render(self, *contexts): 747 def render(self, *contexts):
740 """ Renders this template given a variable number of "contexts" to read 748 """ Renders this template given a variable number of "contexts" to read
741 out values from (such as those appearing in {{foo}}). 749 out values from (such as those appearing in {{foo}}).
742 """ 750 """
743 globalContexts = [] 751 globalContexts = []
744 for context in contexts: 752 for context in contexts:
745 globalContexts.append(context) 753 globalContexts.append(context)
746 renderState = RenderState(globalContexts, []) 754 renderState = RenderState(globalContexts, [])
747 self._topNode.render(renderState) 755 self._topNode.render(renderState)
748 return renderState.getResult() 756 return renderState.getResult()
OLDNEW
« no previous file with comments | « third_party/handlebar/README.chromium ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698