135 lines
3.7 KiB
Python
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)
|