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('''

Login to access

''', '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)