diff --git a/scripts/blog.py b/scripts/blog.py index 93d7c8f..74a5800 100644 --- a/scripts/blog.py +++ b/scripts/blog.py @@ -23,6 +23,7 @@ import time import re from typing import List +from bs4 import BeautifulSoup as bs4 import jinja2 import inotify.adapters import yaml @@ -40,6 +41,9 @@ ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) STATIC_PATH = os.path.join(ROOT_DIR, 'static') ARTICLE_TEMPLATE_NAME = 'article.tmpl.html' +BLOG_INDEX_TEMPLATE_NAME = 'blog_index.tmpl.html' +BLOG_INDEX_PAGE_SIZE = 10 + STATIC_RESOURCES = ( ('style.css', 'css/style.css'), ('light-syntax.css', 'css/light-syntax.css'), @@ -54,6 +58,8 @@ JINJA_ENV = jinja2.Environment( def update_statics(): global ARTICLE_TEMPLATE ARTICLE_TEMPLATE = JINJA_ENV.get_template(ARTICLE_TEMPLATE_NAME) + global BLOG_INDEX_TEMPLATE + BLOG_INDEX_TEMPLATE = JINJA_ENV.get_template(BLOG_INDEX_TEMPLATE_NAME) update_statics() @@ -74,7 +80,13 @@ def parse_nikola_date(match): month=int(match.group(2)), day=int(match.group(1)), hour=int(match.group(4)), - minute=int(match.group(5))) + minute=int(match.group(5)), + # Note this final assumption is not good + # and might get you in trouble if trying + # to sort closely-published posts + # when others are in complete-date format + tzinfo=datetime.timezone.utc, + ) def parse_complete_date(match): @@ -179,9 +191,43 @@ def render_article(doc, front_matter, f): ) f.write(result) +def summarize(doc): + return bs4(doc, features='lxml').text[:1000] + +def render_index(docs, dest_top): + docs = sorted(docs.values(), key=lambda x: x[1]['date'], reverse=True) + + for off in range(0, len(docs), BLOG_INDEX_PAGE_SIZE): + page = docs[off: off + BLOG_INDEX_PAGE_SIZE] + + posts = [ + { + "doc": doc, + "title": front_matter['title'], + "post_publication_date": front_matter['date'], + "post_tags": split_tags(front_matter['tags']), + "summary": summarize(doc), + } + for (doc, front_matter, out_path) in page + ] + + result = BLOG_INDEX_TEMPLATE.render( + posts=posts, + ) + + if off == 0: + fname = 'index.html' + else: + fname = 'index-{}.html'.format(off // BLOG_INDEX_PAGE_SIZE) + with open(os.path.join(dest_top, fname), 'wt') as f: + f.write(result) + + def regen_all(source_top, dest_top, docs=None): if docs is None: docs = load_all(source_top) + + # Render posts for (doc, front_matter, out_path) in docs.values(): doc_full_path = os.path.join(dest_top, out_path) os.makedirs(os.path.dirname(doc_full_path), exist_ok=True) @@ -194,7 +240,7 @@ def regen_all(source_top, dest_top, docs=None): logging.error("Rendering failed 😿") continue - + # Render statics for static in STATIC_RESOURCES: src_path = static[0] dest_path = static[1] @@ -211,6 +257,9 @@ def regen_all(source_top, dest_top, docs=None): with open(target_dest, 'wt') as f: f.write(data) + # Render index + render_index(docs, dest_top) + return docs diff --git a/static/blog_index.tmpl.html b/static/blog_index.tmpl.html new file mode 100644 index 0000000..4be44b9 --- /dev/null +++ b/static/blog_index.tmpl.html @@ -0,0 +1,52 @@ + + +
+ +