Skip to content

Instantly share code, notes, and snippets.

@WizardOfArc
Created June 9, 2021 22:32
Show Gist options
  • Select an option

  • Save WizardOfArc/1381979a1a16ebfe283e814565d07c35 to your computer and use it in GitHub Desktop.

Select an option

Save WizardOfArc/1381979a1a16ebfe283e814565d07c35 to your computer and use it in GitHub Desktop.
My Html Helper - to prevent me from messing up the html, let the program handle opening and closing tags
"""
To Use:
Build your dom structure out of these elements and then call render.()
on the document object to get the dom rendered as a string - either print that out
or write it to a file
"""
class Document:
def __init__(self, dom_elements):
self._dom_elements = dom_elements
def render(self):
lines = []
lines.append('<!DOCTYPE HTML>')
lines.append('<html>')
for de in self._dom_elements:
lines.append(de.render(1))
lines.append('</html>')
return '\n'.join(lines)
def _paddit(level):
return ''.join(' ' for _ in range(level) )
class TextNode:
def __init__(self, text):
self._text = text
def render(self, depth):
lines = [f'{_paddit(depth)}{l}' for l in self._text.split('\n')]
return '\n'.join(lines)
class Attributes:
def __init__(self, attributes_dict):
self._dict = attributes_dict
def render(self):
atts = []
if len(self._dict) == 0:
return ''
for k,v in self._dict.items():
if k == 'style':
# style is a dict
value = str(v).replace("'",'')
elif k == 'class':
# class is a list of classes
value = ' '.join(v)
else:
value = v
atts.append(f'{k}="{value}"')
return f' {" ".join(atts)}'
class DomElement:
def __init__(self, type_name, attributes, self_closing, children):
self._type_name = type_name
self._attributes = attributes
self._self_closing = self_closing
self._children = children
def render(self, depth):
lines = []
phrases = []
padding = _paddit(depth)
phrases.append(f'{padding}<{self._type_name}')
phrases.append(self._attributes.render())
if self._self_closing:
phrases.append('/>')
lines.append(''.join(phrases))
else:
phrases.append('>')
lines.append(''.join(phrases))
for c in self._children:
lines.append(c.render(depth+1))
lines.append(f'{padding}</{self._type_name}>')
return '\n'.join(lines)
class Body(DomElement):
def __init__(self, attributes, children):
super().__init__('body', attributes, False, children)
class CSS:
def __init__(self, content_string):
self._content = content_string
def render(self, depth):
broken = content_string.split('\n')
return '\n'.join( f'{paddit(depth)}{broken}')
class Head(DomElement):
def __init__(self, attributes, children):
super().__init__( 'head', attributes, False, children)
class Base(DomElement):
def __init__(self, attributes, children):
super().__init__( 'base', attributes, False, children)
class Link(DomElement):
def __init__(self, attributes, children):
super().__init__( 'link', attributes, False, children)
class Title(DomElement):
def __init__(self, attributes, children):
super().__init__( 'title', attributes, False, children)
class Meta(DomElement):
def __init__(self, attributes, children):
super().__init__( 'meta', attributes, False, children)
class Script(DomElement):
def __init__(self, attributes, children):
super().__init__( 'script', attributes, False, children)
class Span(DomElement):
def __init__(self, attributes, children):
super().__init__( 'span', attributes, False, children)
class Anchor(DomElement):
def __init__(self, attributes, children):
super().__init__( 'a', attributes, False, children)
class Code(DomElement):
def __init__(self, attributes, children):
super().__init__( 'code', attributes, False, children)
class Style(DomElement):
def __init__(self, css):
super().__init__( 'style', Attributes({}), False, [css])
class Br(DomElement):
def __init__(self):
super().__init__( 'br', Attributes({}), True, [])
class Hr(DomElement):
def __init__(self):
super().__init__('hr', Attributes({}), True, [])
class Div(DomElement):
def __init__(self, attributes, children):
super().__init__('div', attributes, False, children)
class Table(DomElement):
def __init__(self, attributes, children):
super().__init__('table', attributes, False, children)
class TR(DomElement):
def __init__(self, attributes, children):
super().__init__('tr', attributes, False, children)
class TD(DomElement):
def __init__(self, attributes, children):
super().__init__('td', attributes, False, children)
class TH(DomElement):
def __init__(self, attributes, children):
super().__init__('th', attributes, False, children)
class ListElement(DomElement):
def __init__(self, attributes, children):
super().__init__('li', attributes, False, children)
class OrderedList(DomElement):
def __init__(self, attributes, children):
super().__init__('ol', attributes, False, children)
class UnorderedList(DomElement):
def __init__(self, attributes, children):
super().__init__('ul', attributes, False, children)
class Paragraph(DomElement):
def __init__(self, attributes, children):
super().__init__('p', attributes, False, children)
class Heading(DomElement):
def __init__(self, level, attributes, children):
if level > 6:
lvl = 6
elif level < 1:
lvl = 1
else:
lvl = level
super().__init__(f'h{lvl}', attributes, False, children)
@WizardOfArc
Copy link
Copy Markdown
Author

from azi_html import *


def main():
    empty_atts = Attributes({})
    greetings = TextNode("Hello there!")
    description = TextNode("""
How about I just grab some text to paste in here?
The &lt;dfn&gt; HTML element is used to indicate the term being defined within the context of a definition phrase or sentence. The p element, the dt/dd pairing, or the section element which is the nearest ancestor of the &lt;dfn&gt; is considered to be the definition of the term.
""")
    head = Head(empty_atts, [Title(empty_atts, [TextNode('My Page')])])
    body_elements = [
        Heading(1, empty_atts, [TextNode("Heading One!")]),
        Heading(2, empty_atts, [TextNode("Heading Two!")]),
        Heading(3, empty_atts, [TextNode("Heading Three!")]),
        Heading(4, empty_atts, [TextNode("Heading Four!")]),
        Heading(5, empty_atts, [TextNode("Heading Five!")]),
        Heading(6, empty_atts, [TextNode("Heading Six!")]),
        Paragraph(empty_atts, [greetings]),
        Div(empty_atts, [Paragraph(empty_atts, [description])])

    ]

    body = Body(empty_atts, body_elements)
    dom_elements = [head, body]
    html = Document(dom_elements)


    print(html.render())


if __name__ == '__main__':
    main()


☝️ this is example code to use the above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment