{ "cells": [ { "cell_type": "markdown", "id": "dda60de8", "metadata": {}, "source": [ "## Roadmap\n", "\n", "- [x] Load markdown\n", "- [] Determine static website structure\n", " - Where to put assets for subsites like dogma jimfinium\n", " - How to otherwise organize pages\n", "- [x] ~~Resolve markdown links~~\n", "- [] Consider separating article templates and overall page templates\n", "- [] RSS feed\n", "\n", "\n", "WEBROOT\n", "- assets\n", "- main pages\n", "- resume\n", "- dogma-jimfinium/\n", " - assets/\n", " - pages" ] }, { "cell_type": "code", "execution_count": null, "id": "207d2510", "metadata": {}, "outputs": [], "source": [ "import os\n", "import shutil\n", "import markdown\n", "import yaml\n", "import subprocess\n", "import rfeed\n", "import pydantic\n", "from typing import Optional, Union, Literal, BinaryIO, Any\n", "\n", "\n", "\n", "from datetime import datetime\n", "from main import *" ] }, { "cell_type": "code", "execution_count": null, "id": "4b17a3ed", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'dist/assets'" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "PARTIALS = load_partials()\n", "shutil.rmtree('dist/assets', ignore_errors=True)\n", "shutil.copytree('assets','dist/assets')" ] }, { "cell_type": "code", "execution_count": null, "id": "d2361c42", "metadata": {}, "outputs": [ { "ename": "ValidationError", "evalue": "2 validation errors for ArticleMetadata\ndate\n Input should be a valid string [type=string_type, input_value=datetime.date(2026, 1, 30), input_type=date]\n For further information visit https://errors.pydantic.dev/2.12/v/string_type\nlastmod\n Field required [type=missing, input_value={'title': 'Welcome', 'dat...shed': True, 'tags': []}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.12/v/missing", "output_type": "error", "traceback": [ "\u001b[31m---------------------------------------------------------------------------\u001b[39m", "\u001b[31mValidationError\u001b[39m Traceback (most recent call last)", "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[3]\u001b[39m\u001b[32m, line 1\u001b[39m\n\u001b[32m----> \u001b[39m\u001b[32m1\u001b[39m metadata, content = \u001b[43mload_markdown\u001b[49m\u001b[43m(\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43mpages/home.md\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 2\u001b[39m \u001b[38;5;66;03m# content = content.replace('src=\"assets', 'src=\"../tmp/dogma-jimfinium/assets')\u001b[39;00m\n", "\u001b[36mFile \u001b[39m\u001b[32m~/projects/shepich.com/main.py:59\u001b[39m, in \u001b[36mload_markdown\u001b[39m\u001b[34m(md)\u001b[39m\n\u001b[32m 56\u001b[39m \u001b[38;5;66;03m# Convert the contents to a HTML string.\u001b[39;00m\n\u001b[32m 57\u001b[39m content = markdown.markdown(raw_article)\n\u001b[32m---> \u001b[39m\u001b[32m59\u001b[39m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mArticleMetadata\u001b[49m\u001b[43m(\u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mmetadata\u001b[49m\u001b[43m)\u001b[49m, content\n", "\u001b[36mFile \u001b[39m\u001b[32m~/projects/shepich.com/.venv/lib/python3.12/site-packages/pydantic/main.py:250\u001b[39m, in \u001b[36mBaseModel.__init__\u001b[39m\u001b[34m(self, **data)\u001b[39m\n\u001b[32m 248\u001b[39m \u001b[38;5;66;03m# `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks\u001b[39;00m\n\u001b[32m 249\u001b[39m __tracebackhide__ = \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[32m--> \u001b[39m\u001b[32m250\u001b[39m validated_self = \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m.\u001b[49m\u001b[43m__pydantic_validator__\u001b[49m\u001b[43m.\u001b[49m\u001b[43mvalidate_python\u001b[49m\u001b[43m(\u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mself_instance\u001b[49m\u001b[43m=\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[32m 251\u001b[39m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m validated_self:\n\u001b[32m 252\u001b[39m warnings.warn(\n\u001b[32m 253\u001b[39m \u001b[33m'\u001b[39m\u001b[33mA custom validator is returning a value other than `self`.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[33m'\u001b[39m\n\u001b[32m 254\u001b[39m \u001b[33m\"\u001b[39m\u001b[33mReturning anything other than `self` from a top level model validator isn\u001b[39m\u001b[33m'\u001b[39m\u001b[33mt supported when validating via `__init__`.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[33m\"\u001b[39m\n\u001b[32m 255\u001b[39m \u001b[33m'\u001b[39m\u001b[33mSee the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.\u001b[39m\u001b[33m'\u001b[39m,\n\u001b[32m 256\u001b[39m stacklevel=\u001b[32m2\u001b[39m,\n\u001b[32m 257\u001b[39m )\n", "\u001b[31mValidationError\u001b[39m: 2 validation errors for ArticleMetadata\ndate\n Input should be a valid string [type=string_type, input_value=datetime.date(2026, 1, 30), input_type=date]\n For further information visit https://errors.pydantic.dev/2.12/v/string_type\nlastmod\n Field required [type=missing, input_value={'title': 'Welcome', 'dat...shed': True, 'tags': []}, input_type=dict]\n For further information visit https://errors.pydantic.dev/2.12/v/missing" ] } ], "source": [ "metadata, content = load_markdown('pages/home.md')\n", "# content = content.replace('src=\"assets', 'src=\"../tmp/dogma-jimfinium/assets')" ] }, { "cell_type": "code", "execution_count": null, "id": "0bb15524", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "ed7b3b2f", "metadata": {}, "outputs": [], "source": [ "html = format_html_template('templates/pages/default.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)" ] }, { "cell_type": "code", "execution_count": null, "id": "b8c87620", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "57383c24", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2025-12-01\n" ] }, { "data": { "text/plain": [ "CompletedProcess(args=['cp', 'build/resume/2025-12-01/shepich_resume.pdf', 'dist/shepich_resume.pdf'], returncode=0, stdout=b'', stderr=b'')" ] }, "execution_count": 170, "metadata": {}, "output_type": "execute_result" } ], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "944a5efd", "metadata": {}, "outputs": [], "source": [ "shutil.rmtree('dist/dogma-jimfinium', ignore_errors=True)\n", "os.makedirs('dist/dogma-jimfinium', exist_ok=True)\n", "shutil.copytree('build/dogma-jimfinium/assets', 'dist/dogma-jimfinium/assets')\n", "\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/pages/default.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', **PARTIALS)\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": "132a32ec", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "datetime.date(2024, 7, 12)" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "metadata['date']" ] }, { "cell_type": "code", "execution_count": null, "id": "d48110fc", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "datetime.datetime(2024, 7, 12, 0, 0)" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "datetime(metadata['date'].year, metadata['date'].month, metadata['date'].day)" ] }, { "cell_type": "code", "execution_count": null, "id": "e32458c7", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Dogma Jimfiniumhttp://localhost:8000/dogma-jimfinium/rssDogma Jimfiniumen-USThu, 29 Jan 2026 16:29:57 GMTrfeed v1.1.1https://github.com/svpino/rfeed/blob/master/README.mdSuperlockhttp://localhost:8000/dogma-jimfinium/superlockJim Shepich IIIWed, 26 Nov 2025 00:00:00 GMTsuperlockSustainable Livinghttp://localhost:8000/dogma-jimfinium/sustainable-livingJim Shepich IIIThu, 20 Nov 2025 00:00:00 GMTsustainable-livingStocking Uphttp://localhost:8000/dogma-jimfinium/stocking-upJim Shepich IIIWed, 19 Nov 2025 00:00:00 GMTstocking-upSet Up the Toyshttp://localhost:8000/dogma-jimfinium/set-up-the-toysJim Shepich IIIWed, 14 Jan 2026 00:00:00 GMTset-up-the-toysDo What You Lovehttp://localhost:8000/dogma-jimfinium/do-what-you-loveJim Shepich IIITue, 10 Jun 2025 00:00:00 GMTdo-what-you-loveSelf-Care is not Selfishhttp://localhost:8000/dogma-jimfinium/self-care-is-not-selfishJim Shepich IIISun, 18 May 2025 00:00:00 GMTself-care-is-not-selfishBlowoutshttp://localhost:8000/dogma-jimfinium/blowoutsJim Shepich IIIWed, 26 Nov 2025 00:00:00 GMTblowoutsVitamins & Supplementshttp://localhost:8000/dogma-jimfinium/vitaminsJim Shepich IIISun, 18 May 2025 00:00:00 GMTvitaminsGear for New Parentshttp://localhost:8000/dogma-jimfinium/gear-for-new-parentsJim Shepich IIIFri, 12 Jul 2024 00:00:00 GMTgear-for-new-parents\n" ] } ], "source": [ "rss_feed = rfeed.Feed(\n", " title = \"Dogma Jimfinium\",\n", " link = \"http://localhost:8000/dogma-jimfinium/rss\",\n", " description = \"Dogma Jimfinium\",\n", " language = \"en-US\",\n", " lastBuildDate = datetime.now(),\n", " items = [\n", " rfeed.Item(\n", " title = metadata['title'],\n", " link = f\"http://localhost:8000/dogma-jimfinium/{filestem}\", \n", " description = metadata.get('description'),\n", " author = metadata.get('author', 'Jim Shepich III'),\n", " guid = rfeed.Guid(filestem),\n", " pubDate = datetime(metadata['date'].year, metadata['date'].month, metadata['date'].day)\n", " )\n", " for filestem, (metadata, _) in index.items()\n", " ]\n", ")\n", "\n", "print(rss_feed.rss())" ] }, { "cell_type": "code", "execution_count": null, "id": "6c160693", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "57ef8185", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "b068c448", "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "id": "e3171afd", "metadata": {}, "outputs": [], "source": [ "def build_site(site_config: SiteConfig):\n", " " ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }