From 006aeab2c14f8c99e064d748d7da66c0b91d506d Mon Sep 17 00:00:00 2001 From: Jim Shepich III Date: Thu, 29 Jan 2026 10:09:32 -0500 Subject: [PATCH] Added blog archive --- assets/css/theme.css | 28 +++++ .../partials/blog_article.html => config.yaml | 0 main.py | 34 +++++- templates/{default.html => blog_post.html} | 5 +- templates/components/blog_archive_li.html | 1 + templates/components/blog_article.html | 11 ++ templates/components/blog_tag.html | 1 + templates/partials/nav.html | 3 +- templates/simple.html | 14 +++ testbench.ipynb | 107 ++++++++++++++---- 10 files changed, 180 insertions(+), 24 deletions(-) rename templates/partials/blog_article.html => config.yaml (100%) rename templates/{default.html => blog_post.html} (96%) create mode 100644 templates/components/blog_archive_li.html create mode 100644 templates/components/blog_article.html create mode 100644 templates/components/blog_tag.html create mode 100644 templates/simple.html diff --git a/assets/css/theme.css b/assets/css/theme.css index cc1e447..c66247f 100644 --- a/assets/css/theme.css +++ b/assets/css/theme.css @@ -145,3 +145,31 @@ summary.heading{ -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-tap-highlight-color: transparent; } + +span.blog-tag{ + font-weight: bold; + border-radius: 3px 3px 3px 3px; + background-color: var(--azure); + color: white; + font-size: 0.6em; + padding: 0.1em; + padding-left: 0.5em; + padding-right: 0.5em; + vertical-align: middle; +} + +span.blog-tag:hover{ + background-color: var(--azure-tint-20); +} + +a:has(> span.blog-tag){ + vertical-align: middle; + color: unset; + text-decoration: unset; + font-weight: unset; +} + +article > hr{ + border: 0.1rem solid var(--silver); + box-shadow: none; +} \ No newline at end of file diff --git a/templates/partials/blog_article.html b/config.yaml similarity index 100% rename from templates/partials/blog_article.html rename to config.yaml diff --git a/main.py b/main.py index cb46608..23ffae5 100644 --- a/main.py +++ b/main.py @@ -76,4 +76,36 @@ def load_partials() -> dict: partial_template, current_year = datetime.now().year ) - return partials \ No newline at end of file + return partials + + +def import_resume(): + + # Use a sentinel value for the loop. + max_date = '0000-00-00' + + # Loop through the folders in the resume repo to find the most recent one. + for resume_folder in os.listdir('build/resume'): + + # Skip folders that are not in YYYY-MM-DD format. + try: + datetime.strptime(resume_folder,'%Y-%m-%d') + except Exception: + continue + + # Keep track of the most recent date. + if resume_folder > max_date: + max_date = resume_folder + + # Copy the resume into the /dist directory. + run(f'cp build/resume/{max_date}/shepich_resume.pdf dist/shepich_resume.pdf') + + +def format_blog_tags(tags: list[str], template = 'templates/components/blog_tag.html') -> list[str]: + '''Generates HTML blog tag components from a list of tag names.''' + return [ + format_html_template(template, tag_name = t) for t in tags + ] + +if __name__ == '__main__': + pass \ No newline at end of file diff --git a/templates/default.html b/templates/blog_post.html similarity index 96% rename from templates/default.html rename to templates/blog_post.html index 3cc4d24..227fdfd 100644 --- a/templates/default.html +++ b/templates/blog_post.html @@ -1,5 +1,4 @@ - @@ -7,9 +6,8 @@ {partials__header} {partials__nav} - - +

{metadata__title}

{content}
+
{partials__footer} \ No newline at end of file diff --git a/templates/components/blog_archive_li.html b/templates/components/blog_archive_li.html new file mode 100644 index 0000000..a06da53 --- /dev/null +++ b/templates/components/blog_archive_li.html @@ -0,0 +1 @@ +
  • {metadata__date} - {metadata__title} {blog_tags}
  • diff --git a/templates/components/blog_article.html b/templates/components/blog_article.html new file mode 100644 index 0000000..b8acdf0 --- /dev/null +++ b/templates/components/blog_article.html @@ -0,0 +1,11 @@ +
    +

    {metadata__title}

    +
    By
    +
    First published: +
    Last modified: +

    + {content} +
    +

    {blog_tags}

    +
    \ No newline at end of file diff --git a/templates/components/blog_tag.html b/templates/components/blog_tag.html new file mode 100644 index 0000000..1a77d3b --- /dev/null +++ b/templates/components/blog_tag.html @@ -0,0 +1 @@ +{tag_name} \ No newline at end of file diff --git a/templates/partials/nav.html b/templates/partials/nav.html index 9e34918..1c8861f 100644 --- a/templates/partials/nav.html +++ b/templates/partials/nav.html @@ -1,4 +1,5 @@ \ No newline at end of file diff --git a/templates/simple.html b/templates/simple.html new file mode 100644 index 0000000..bcb8ed9 --- /dev/null +++ b/templates/simple.html @@ -0,0 +1,14 @@ + + + + + {partials__default_css} + {partials__header} + {partials__nav} + + +
    + {content} +
    + {partials__footer} + \ No newline at end of file diff --git a/testbench.ipynb b/testbench.ipynb index 9269cad..b36751b 100644 --- a/testbench.ipynb +++ b/testbench.ipynb @@ -11,7 +11,7 @@ "- [] Determine static website structure\n", " - Where to put assets for subsites like dogma jimfinium\n", " - How to otherwise organize pages\n", - "- [] Resolve markdown links\n", + "- [x] ~~Resolve markdown links~~\n", "- [] Consider separating article templates and overall page templates\n", "- [] RSS feed\n", "\n", @@ -27,7 +27,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 11, "id": "207d2510", "metadata": {}, "outputs": [], @@ -44,7 +44,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 12, "id": "d2361c42", "metadata": {}, "outputs": [], @@ -55,13 +55,13 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 31, "id": "ed7b3b2f", "metadata": {}, "outputs": [], "source": [ "PARTIALS = load_partials()\n", - "html = format_html_template('templates/default.html', content = content, **{'metadata__'+k:v for k,v in metadata.items()}, **PARTIALS)\n", + "html = format_html_template('templates/blog_post.html', content = content, **{'metadata__'+k:v for k,v in metadata.items()}, **PARTIALS)\n", "with open('dist/home.html', 'w') as f:\n", " f.write(html)" ] @@ -98,23 +98,92 @@ "output_type": "execute_result" } ], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 58, + "id": "944a5efd", + "metadata": {}, + "outputs": [], "source": [ - "def get_latest_resume():\n", - " max_date = '0000-00-00'\n", - " for resume_folder in os.listdir('build/resume'):\n", - " try:\n", - " datetime.strptime(resume_folder,'%Y-%m-%d')\n", - " except Exception:\n", - " continue\n", - " \n", - " if resume_folder > max_date:\n", - " max_date = resume_folder\n", - " \n", + "run(f'rm -rf dist/dogma-jimfinium && mkdir -p dist/dogma-jimfinium')\n", + "run(f'cp -r build/dogma-jimfinium/assets dist/dogma-jimfinium')\n", "\n", - " print(max_date)\n", - " # print(max_date.strftime('%Y-%m-%d'))\n", + "index = {}\n", + "\n", + "for article in os.listdir('build/dogma-jimfinium'):\n", + " metadata, content = load_markdown(f'build/dogma-jimfinium/{article}')\n", + "\n", + " # Skip unpublished articles.\n", + " if not metadata.get('published'):\n", + " continue\n", + "\n", + " article_filestem = os.path.splitext(article)[0]\n", + "\n", + " # Add the article to the index.\n", + " index[article_filestem] = (metadata, content)\n", + "\n", + " # Interpolate the article contents into the webpage template.\n", + " article_html = format_html_template(\n", + " 'templates/components/blog_article.html',\n", + " content = content,\n", + " blog_tags = ' '.join(format_blog_tags(metadata['tags'])),\n", + " **{'metadata__'+k:v for k,v in metadata.items()}\n", + " )\n", + " html = format_html_template('templates/simple.html', content = article_html, **PARTIALS)\n", + " \n", + " # Write the HTML file to /dist/dogma-jimfinium.\n", + " with open(f'dist/dogma-jimfinium/{article_filestem}.html', 'w') as f:\n", + " f.write(html)\n", + "\n", + "\n", + "index_html = build_blog_archive(index, metadata__title = 'Dogma Jimfinium | Index')\n", + "# Write the HTML file to /dist/dogma-jimfinium.\n", + "with open(f'dist/dogma-jimfinium/index.html', 'w') as f:\n", + " f.write(index_html)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e32458c7", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3171afd", + "metadata": {}, + "outputs": [], + "source": [ + "def build_blog_archive(index: dict[str, tuple[str, str]], template = 'templates/simple.html', **kwargs) -> str:\n", + " '''Converts an index, formatted as filestem: (metadata, contents) dict,\n", + " into an HTML page containing the list of articles, sorted from newest to oldest.'''\n", + "\n", + " # Add each article in the format `YYYY-MM-DD - Title`\n", + " index_html_content = ''\n", + "\n", + " index_html_page = format_html_template(\n", + " template, \n", + " content = index_html_content, \n", + " **kwargs,\n", + " **PARTIALS\n", + " )\n", + " \n", + " return index_html_page" ] } ],