Home Blog CV Projects Patterns Notes Book Colophon Search

Start an HTML Template System

5 Oct, 2023

Here's a very simple way of starting an HTML template system.

import html

class Html:
    def __init__(self, escaped_html):
        self._escaped_html = escaped_html

    def render(self):
        return self._escaped_html

    def __add__(self, other):
        other_type = type(other)
        if other_type is Html:
            self._escaped_html += other._escaped_html
        elif other_type is str:
            self._escaped_html += html.escape(other, quote=True)
        else:
            raise Exception(f'Unsupported type: {repr(other)}')
        return self


class Base:
    def __init__(self, title, body):
        self._title = title
        self._body = body

    def title(self):
        return self._title

    def body(self):
        return self._body

    def render(self):
        return (
            Html('<!DOCTYPE html>\n<html lang="en">\n  <head>\n    <title>')
            + self.title()
            + Html(
                '</title>\n    <meta name="viewport" content="width=device-width, initial-scale=1.0">\n    <meta charset="UTF-8">\n  </head>\n  <body>\n    <h1>'
            )
            + self.title()
            + Html("</h1>\n")
            + self.body()
            + Html("\n  </body>\n</html>")
        ).render()


class Home(Base):
    def __init__(self, title, links):
        self._title = title
        self._links = links

    def body(self):
        h = Html('    <ul>\n')
        for link, text in self._links:
            h += Html('      <li><a href="') + link + Html('">') + text + Html('</a></li>\n')
        h += Html('    </ul>')
        return h

print(
    Home(
        title='Home',
        links=[
            ('/html', 'HTML'),
            ('/str', 'str'),
            ('/dict', 'dict'),
            ('/bytes', 'bytes'),
            ('/other', 'Other (should raise error)'),
        ]
    ).render()
)

The underlying html.escape() method used by Html() isn't safe for putting content into <css> or <script> tags. Instead have links to external CSS and javascript files.

The output is:

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Home</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta charset="UTF-8">
  </head>
  <body>
    <h1>Home</h1>
    <ul>
      <li><a href="/html">HTML</a></li>
      <li><a href="/str">str</a></li>
      <li><a href="/dict">dict</a></li>
      <li><a href="/bytes">bytes</a></li>
      <li><a href="/other">Other (should raise error)</a></li>
    </ul>
  </body>
</html>

Comments

Be the first to comment.

Add Comment





Copyright James Gardner 1996-2020 All Rights Reserved. Admin.