diff options
author | David Luevano Alvarado <david@luevano.xyz> | 2021-05-16 18:46:01 -0600 |
---|---|---|
committer | David Luevano Alvarado <david@luevano.xyz> | 2021-05-16 18:46:01 -0600 |
commit | 0dae5d53c49dd7b946990ca9e232fb924bf4f918 (patch) | |
tree | 93d4e990a9351a139339e2baf91d82b45849ddb4 /src/pyssg/builder.py | |
parent | eaee38a4b6ebedc106548876cdbe1fe433c514bb (diff) |
refactor code and finish basic features
Diffstat (limited to 'src/pyssg/builder.py')
-rw-r--r-- | src/pyssg/builder.py | 318 |
1 files changed, 278 insertions, 40 deletions
diff --git a/src/pyssg/builder.py b/src/pyssg/builder.py index 002d80e..2ba1b6c 100644 --- a/src/pyssg/builder.py +++ b/src/pyssg/builder.py @@ -1,44 +1,282 @@ import os import shutil +from copy import deepcopy +from .template import Template from .database import Database -from .discovery import get_all_files -from .converter import create_html_files - - -def create_dir_structure(dst: str, - dirs: list[str]) -> None: - for d in dirs: - # for the dir structure, - # doesn't matter if the dir already exists - try: - os.makedirs(os.path.join(dst, d)) - except FileExistsError: - pass - - -def copy_html_files(src: str, - dst: str, - files: list[str], - db: Database) -> None: - src_file = None - dst_file = None - - for f in files: - src_file = os.path.join(src, f) - dst_file = os.path.join(dst, f) - - # only copy files if they have been modified (or are new) - if db.update(src_file, remove=f'{src}/'): - shutil.copy2(src_file, dst_file) - - -def build_static_site(src: str, - dst: str, - db: Database) -> None: - # get all file data and create necessary dir structure - dirs, md_files, html_files = get_all_files(src) - create_dir_structure(dst, dirs) - - copy_html_files(src, dst, html_files, db) - create_html_files(src, dst, md_files, db) +from .parser import MDParser +from .page import Page +from .discovery import get_file_list, get_dir_structure + +class HTMLBuilder: + def __init__(self, src: str, + dst: str, + base_url: str, + template: Template, + db: Database, + dformat: str=None, + l_dformat: str=None, + lsep_dformat: str=None): + self.src: str = src + self.dst: str = dst + self.base_url: str = base_url + self.template: Template = template + self.db: Database = db + self.dformat: str = None + self.l_dformat: str = None + self.lsep_dformat: str = None + + if dformat is not None: + self.dformat = dformat + else: + self.dformat = "%a, %d %b, %Y @ %H:%M %Z" + + if l_dformat is not None: + self.l_dformat = l_dformat + else: + self.l_dformat = "%b %d" + + if lsep_dformat is not None: + self.lsep_dformat = lsep_dformat + else: + self.lsep_dformat = "%B %Y" + + self.dirs: list[str] = None + self.md_files: list[str] = None + self.html_files: list[str] = None + + + def build(self) -> None: + self.dirs = get_dir_structure(self.src, ['templates']) + self.md_files = get_file_list(self.src, ['.md'], ['templates']) + self.html_files = get_file_list(self.src, ['.html'], ['templates']) + + self.__create_dir_structure() + self.__copy_html_files() + + parser: MDParser = MDParser(self.src, self.md_files, self.db) + parser.parse() + + # create the article index + self.__create_article_index(parser.all_tags, parser.all_pages) + + # create each category of html pages + self.__create_articles(parser.updated_pages) + self.__create_tags(parser.all_tags, parser.all_pages) + + + def __create_dir_structure(self) -> None: + for d in self.dirs: + # for the dir structure, + # doesn't matter if the dir already exists + try: + os.makedirs(os.path.join(self.dst, d)) + except FileExistsError: + pass + + + def __copy_html_files(self) -> None: + src_file: str = None + dst_file: str = None + + for f in self.html_files: + src_file = os.path.join(self.src, f) + dst_file = os.path.join(self.dst, f) + + # only copy files if they have been modified (or are new) + if self.db.update(src_file, remove=f'{self.src}/'): + shutil.copy2(src_file, dst_file) + + + # this is really similar to create_tag (singular) + def __create_article_index(self, tags: list[str], + pages: list[Page]) -> None: + # make temporary template + t: Template = deepcopy(self.template) + + # do basic replacements + # get page and tag list formated, both functions do replacements + p_list: list[str] = self.__get_pages_formatted(pages, t) + t_list: list[str] = self.__get_tags_formatted(tags, t) + # common + t.header = t.header.replace("$$LANG", 'en') + t.header = t.header.replace('$$TITLE', f'Index') + + with open(os.path.join(self.dst, 'index.html'), 'w') as f: + f.write(t.header) + f.write(t.articles.header) + + f.write(t.tags.list_header) + for tag in t_list: + f.write(tag) + f.write(t.tags.list_footer) + + f.write(t.articles.list_header) + for page in p_list: + f.write(page) + f.write(t.articles.list_footer) + + f.write(t.articles.footer) + f.write(t.footer) + + + def __create_articles(self, pages: list[Page]) -> None: + for p in pages: + self.__create_article(p) + + + def __create_article(self, page: Page) -> None: + # TODO: create better solution for replace + # make temporary template + t: Template = deepcopy(self.template) + + # prepare html file name + f_name: str = page.name + f_name = f_name.replace('.md', '.html') + + # get timestamps + c_date: str = page.c_datetime.strftime(self.dformat) + m_date: str = None + if page.m_datetime is not None: + m_date: str = page.m_datetime.strftime(self.dformat) + + # do basic replacements + # get tag list formatted (some replacements done inside + # get_tags_formatted) + t_list: list[str] = None + if page.tags is not None: + t_list = self.__get_tags_formatted(page.tags, t) + + # common + t.header = t.header.replace("$$LANG", page.lang) + t.header = t.header.replace('$$TITLE', page.title) + + # article header + t.article.header = t.article.header.replace('$$TITLE', page.title) + t.article.header = t.article.header.replace('$$AUTHOR', page.author) + t.article.header = t.article.header.replace('$$CTIME', c_date) + if m_date is not None: + t.article.header = t.article.header.replace('$$MTIME', m_date) + else: + t.article.header = t.article.header.replace('$$MTIME', '') + + # article footer (same replaces as header) + t.article.footer = t.article.footer.replace('$$TITLE', page.title) + t.article.footer = t.article.footer.replace('$$AUTHOR', page.author) + t.article.footer = t.article.footer.replace('$$CTIME', c_date) + if m_date is not None: + t.article.footer = t.article.footer.replace('$$MTIME', m_date) + else: + t.article.footer = t.article.footer.replace('$$MTIME', '') + + + with open(os.path.join(self.dst, f_name), 'w') as f: + f.write(t.header) + f.write(t.article.header) + f.write(page.html) + + if t_list is not None: + f.write(t.tags.list_header) + for tag in t_list: + f.write(tag) + f.write(t.tags.list_footer) + + f.write(t.article.footer) + f.write(t.footer) + + + def __get_tags_formatted(self, tags: list[str], + template: Template) -> list[str]: + tag_amount: int = len(tags) + tags_formatted: list[str] = [] + for i, t in enumerate(tags): + # t_e=tag entry + t_e: str = template.tags.list_entry + t_e = t_e.replace('$$URL', + f'{self.base_url}/tag/@{t}.html') + t_e = t_e.replace('$$NAME', t) + + tags_formatted.append(t_e) + if i != tag_amount - 1: + tags_formatted.append(template.tags.list_separator) + + return tags_formatted + + + def __create_tags(self, tags: list[str], + pages: list[Page]) -> None: + for t in tags: + # get a list of all pages that have current tag + # and sort them (by time) + tag_pages: list[Page] = [] + for p in pages: + if p.tags is not None and t in p.tags: + tag_pages.append(p) + tag_pages.sort(reverse=True) + + # build tag page + self.__create_tag(t, tag_pages) + + # clean list of pages with current tag + tag_pages = [] + + + def __create_tag(self, tag: str, + pages: list[Page]) -> None: + # TODO: create better solution for replace + # make temporary template + t: Template = deepcopy(self.template) + + # do basic replacements + # get page list formated (some replacements done inside + # get_pages_formatted) + p_list: list[str] = self.__get_pages_formatted(pages, t) + # common + t.header = t.header.replace("$$LANG", 'en') + t.header = t.header.replace('$$TITLE', f'Posts filtered by: {tag}') + + # tag header + tag_url: str = f'{self.base_url}/tag/@{tag}.html' + t.tags.header = t.tags.header.replace('$$NAME', tag) + t.tags.header = t.tags.header.replace('$$URL', tag_url) + + with open(os.path.join(self.dst, f'tag/@{tag}.html'), 'w') as f: + f.write(t.header) + f.write(t.tags.header) + + f.write(t.articles.list_header) + for p in p_list: + f.write(p) + f.write(t.articles.list_footer) + + f.write(t.tags.footer) + f.write(t.footer) + + + def __get_pages_formatted(self, pages: list[Page], + template: Template) -> list[str]: + month_year: str = '-' + pages_formatted: list[str] = [] + for p in pages: + # check if the monthly separator should be included + c_month_year: str = p.c_datetime.strftime(self.lsep_dformat) + if c_month_year != month_year: + month_year = c_month_year + + month_sep: str = template.articles.list_separator + month_sep = month_sep.replace('$$SEP', month_year) + + pages_formatted.append(month_sep) + + f_name: str = p.name + f_name = f_name.replace('.md', '.html') + + # p_e=page entry + p_e: str = template.articles.list_entry + p_e = p_e.replace('$$URL', f'{self.base_url}/{f_name}') + p_e = p_e.replace('$$DATE', p.c_datetime.strftime(self.l_dformat)) + p_e = p_e.replace('$$TITLE', p.title) + + pages_formatted.append(p_e) + + return pages_formatted |