def test_render_condensed_node_child(self): parent = nodes.HtmlNode('div') child1 = nodes.HtmlNode('p', condensed=True) child2 = nodes.HtmlNode('span') child1.add_child(nodes.TextNode('ptext')) child2.add_child(nodes.TextNode('spantext')) parent.add_child(child1) parent.add_child(child2) lines = parent.render_lines() self.assertEqual([ '<div>', '<p>ptext</p>', '<span>', 'spantext', '</span>', '</div>' ], lines)
def test_multiple_trees(self): parent = nodes.HtmlNode('div') child1 = nodes.HtmlNode('p') child2 = nodes.HtmlNode('span') child1.add_child(nodes.TextNode('ptext')) child2.add_child(nodes.TextNode('spantext')) parent.add_child(child1) parent.add_child(child2) lines = parent.render_lines() self.assertEqual([ '<div>', '<p>', 'ptext', '</p>', '<span>', 'spantext', '</span>', '</div>' ], lines)
def test_render_condensed_node(self): parent = nodes.HtmlNode('div', condensed=True) child = nodes.HtmlNode('p') text = nodes.TextNode('content') parent.add_child(child) child.add_child(text) lines = parent.render_lines() self.assertEqual(['<div><p>', 'content', '</p></div>'], lines)
def test_nested(self): parent = nodes.HtmlNode('div') child = nodes.HtmlNode('p') text = nodes.TextNode('content') parent.add_child(child) child.add_child(text) lines = parent.render_lines() self.assertEqual(['<div>', '<p>', 'content', '</p>', '</div>'], lines)
def build_tree(cls, source_text): """Given HAML source text, parse it into a tree of Nodes.""" source_lines = cls.get_source_lines(source_text) root = nodes.Node() indent_stack = [-1] node_stack = [root] for line_number, line in enumerate(source_lines, start=1): # Ignore all the blank (or whitespace only) lines. if not line.strip(): continue # Figure out how far indented the current line is. try: indent = cls.get_indent_level(line) except Exception, exception: raise TemplateIndentationError(exception.message, line_number) # Either increase the indentation level, or pop nodes off to # de-dent. if indent > indent_stack[-1]: indent_stack.append(indent) else: while indent < indent_stack[-1]: indent_stack.pop() node_stack.pop() node_stack.pop() # If the top of the indent stack isn't the same as this line, then # something went wrong. if indent != indent_stack[-1]: raise TemplateIndentationError( 'Unindent does not match any outer indentation level!', line_number) # The top of the node stack is what we'll consider the 'parent'. parent_node = node_stack[-1] # If we are part of a custom block, don't try to parse anything but # instead treat it all as text. if (isinstance(parent_node, nodes.CustomBlockNode) or parent_node.has_ancestor_of_type(nodes.CustomBlockNode)): node = nodes.TextNode(line.strip()) # Otherwise, turn this line into a proper Node. else: try: node = cls.parse_line(line.strip()) except Exception, exception: raise TemplateSyntaxError(exception.message, line_number)
def parse_line(cls, line): """Parse a given line into a Node object. This method doesn't care about indentation, so line should be stripped of whitespace beforehand. """ if not line: node = nodes.EmptyNode() elif line[0] in (cls.HTML_TAG_PREFIX, '.', '#'): node = nodes.HtmlNode.from_haml(line) elif line[0] in (cls.HTML_COMMENT_PREFIX, ): node = nodes.HtmlCommentNode(line[1:]) elif line[0] in (cls.JINJA_TAG_PREFIX, ): node = nodes.JinjaNode.from_haml(line) elif line[0] in (cls.CUSTOM_BLOCK_PREFIX, ): node = nodes.CustomBlockNode(line[1:]) elif line[0] in (cls.PREFORMATTED_PREFIX, ): node = nodes.PreformattedTextNode(line[1:]) elif line[0] in (cls.ESCAPE_PREFIX, ): node = nodes.TextNode(line[1:]) else: node = nodes.TextNode(line) return node
def test_properly_stores_data(self): node = nodes.TextNode('data') self.assertEqual('data', node.data)
def test_render_end_is_None(self): node = nodes.TextNode('data') self.assertEqual(None, node.render_end())
def test_render_start_shows_just_data(self): node = nodes.TextNode('data') self.assertEqual('data', node.render_start())
def test_requires_data_at_instantiation(self): with self.assertRaises(Exception): node = nodes.TextNode()
def test_simple_content(self): node = nodes.HtmlNode('div') node.add_child(nodes.TextNode('content')) lines = node.render_lines() self.assertEqual(['<div>', 'content', '</div>'], lines)