buranun/generate_html.py

135 lines
3.7 KiB
Python

import urllib.parse
import bs4
import config
import database
def generate_nav(*, soup):
"""Returns nav_tag"""
# TODO: Don't generate link to a board if we're at the index
nav_tag = soup.new_tag('nav')
with database.connect() as db:
boards = database.list_boards(db)
for board in boards:
url = config.url_prefix + '/' + urllib.parse.quote(board, safe = '') + '/'
a_tag = soup.new_tag('a', href = url)
a_tag.string = '/' + board + '/'
nav_tag.append(a_tag)
return nav_tag
def generate_header(*, page_title, soup):
"""Returns header_tag"""
header_tag = soup.new_tag('header')
h1_tag = soup.new_tag('h1')
h1_tag.string = page_title
header_tag.append(h1_tag)
return header_tag
def generate_footer(*, soup):
"""Returns footer_tag"""
# TODO: Add footer generation
return soup.new_tag('footer')
def page_skeleton(*, page_title, contents, soup):
"""Returns html
Given page title (string) and contents (iteratable of beautifulsoup tags), create the html
Since most pages have same basic structure, it makes sense to factor this out from page creation functions"""
# Doctype and head are more or less the same for each page, no need to do anything fancy when adding them
soup.append(bs4.Doctype('html'))
head_tag = soup.new_tag('head')
title_tag = soup.new_tag('title')
title_tag.string = page_title
head_tag.append(title_tag)
soup.append(head_tag)
# Body consists of (more or less same) header and footer, and varying content
body_tag = soup.new_tag('body')
body_tag.append(generate_nav(soup = soup))
body_tag.append(generate_header(page_title = page_title, soup = soup))
# contents is an iterable that can contain several tags
for tag in contents:
body_tag.append(tag)
body_tag.append(generate_footer(soup = soup))
soup.append(body_tag)
# Use .prettify() to generate nice-looking HTML
# We are probably never going to serve enough pages for the additional whitespace to count for data usage
return soup.prettify()
def new_soup():
"""Returns soup
Since we need a soup object to create tags, split this from page_skeleton"""
# Use python's built-in parser for portability
# We'll be constructing the document programmatically, so start with empty tree
soup = bs4.BeautifulSoup('', 'html.parser')
return soup
def board(board_name):
"""Returns html
Creates the board index page"""
# TODO: Creae a board index page
soup = new_soup()
page_title = '/' + board_name + '/'
return page_skeleton(page_title = page_title, contents = [], soup = soup)
def index():
"""Returns html
Create the site index"""
# TODO: Create an index page
soup = new_soup()
return page_skeleton(page_title = config.site_name, contents = [], soup = soup)
def login(raw_path, retrying = False):
"""Returns html
Creates a page telling the user to log in
if retrying is true, show a text about username/pass being wrong"""
# TODO: Take the user back to where they were
soup = new_soup()
# TODO: Don't hardcode
contents = list(bs4.BeautifulSoup('''
<p>Login to access</p>
<form action="''' + config.url_prefix + '''/login" method="post">
<div>
<input type="text" name="username"/>
</div>
<div>
<input type="password" name="password"/>
</div>
<div>
<input type="submit" value="Login"/>
</div>
</form>
''', 'html.parser'))
if retrying:
p_tag = soup.new_tag('p')
p_tag.string = 'Wrong username or password'
contents = [contents[0], p_tag] + contents[1:]
# TODO: Internationalization
return page_skeleton(page_title = 'Login to ' + config.site_name, contents = contents, soup = soup)
def error_404(path):
"""Returns html"""
soup = new_soup()
p_tag = soup.new_tag('p')
p_tag.string = path + ' does not exist'
return page_skeleton(page_title = '404 Not Found', contents = [p_tag], soup = soup)