diff --git a/config.yaml b/config.yaml
index 2ed6b33..931fdc6 100644
--- a/config.yaml
+++ b/config.yaml
@@ -8,9 +8,9 @@ site_defaults:
pages: ./templates/pages
sites:
main:
- build_cache: ./build
+ build_cache: ./site
assets:
- - ./assets
+ - /assets
articles:
- ./pages/*.md
resume:
@@ -24,7 +24,7 @@ sites:
build_cache: ./build/dogma-jimfinium
web_root: ./dist/dogma-jimfinium
assets:
- - '{build_cache}/assets'
+ - assets
articles:
- - '{build_cache}/*.md'
+ - '*.md'
\ No newline at end of file
diff --git a/main.py b/main.py
index 3fca3d1..106fecb 100644
--- a/main.py
+++ b/main.py
@@ -1,4 +1,6 @@
import os
+import glob
+import shutil
import subprocess
import markdown
import yaml
@@ -30,7 +32,7 @@ class ArticleMetadata(pydantic.BaseModel):
title: str
author: Optional[str] = config.get('author')
date: date
- lastmod: Optional[date]
+ lastmod: Optional[date] = None
published: bool
tags: list
thumbnail: Optional[str] = None
@@ -73,20 +75,13 @@ def format_html_template(template: str, **kwargs) -> str:
return html
-REPOS = [
- 'ssh://gitea/jim/resume.git',
- 'ssh://gitea/jim/dogma-jimfinium.git'
-]
run = lambda cmd: subprocess.run(cmd.split(' '), stdout = subprocess.PIPE, stderr = subprocess.PIPE)
-def update_git_repos(repos: list) -> None:
- '''Pulls updates to repos in the build directory, or clones them if they don't exist.'''
- for repo in repos:
- local_path = 'build/'+repo.split('/')[-1].strip('.git')
- print(local_path)
- if os.path.exists(f'{local_path}/.git'):
- run(f'git -C {local_path} pull origin')
- else:
- run(f'git clone {repo} {local_path}')
+def pull_git_repo(repo: str, build_cache: str) -> None:
+ '''Pulls/clones a repo into the build cache directory.'''
+ if os.path.exists(f'{build_cache}/.git'):
+ run(f'git -C {build_cache} pull origin')
+ else:
+ run(f'git clone {repo} {build_cache}')
def load_partials() -> dict:
@@ -147,7 +142,7 @@ def build_blog_archive(
# Add each article as a list item to an unordered list.
archive_html_content = '
'
- for article, (metadata, contents) in sorted(index.items(), key = lambda item: item[1][0]['date'])[::-1]:
+ for article, (metadata, contents) in sorted(index.items(), key = lambda item: item[1][0].date)[::-1]:
# Generate HTML for the article (including metadata tags).
archive_html_content += format_html_template(
@@ -168,5 +163,35 @@ def build_blog_archive(
return archive_html_page
+def copy_assets(site: SiteConfig):
+ '''Copies the list of site assets from the build cache to the web root.'''
+
+ # Expand any globbed expressions.
+ expanded_asset_list = []
+ for a in site.assets:
+ expanded_asset_list.extend(
+ # Assets are defined relative to the build cache; construct the full path.
+ glob.glob(f'{site.build_cache}/{a.lstrip("/")}')
+ )
+
+ for asset in expanded_asset_list:
+
+ # Construct the destination path analogous to the source path
+ # but in the web root instead of the build cache.
+ destination = f'{site.web_root}/{a.lstrip("/")}'
+
+ # Delete existing files.
+ shutil.rmtree(destination, ignore_errors=True)
+
+ # Copy the asset.
+ if os.path.isdir(asset):
+ shutil.copytree(asset, destination)
+ elif os.path.isfile(asset):
+ shutil.copyfile(asset, destination)
+ else:
+ continue
+
+ return None
+
if __name__ == '__main__':
pass
\ No newline at end of file
diff --git a/assets/css/common.css b/site/assets/css/common.css
similarity index 100%
rename from assets/css/common.css
rename to site/assets/css/common.css
diff --git a/assets/css/deprecated.css b/site/assets/css/deprecated.css
similarity index 100%
rename from assets/css/deprecated.css
rename to site/assets/css/deprecated.css
diff --git a/assets/css/layout.css b/site/assets/css/layout.css
similarity index 100%
rename from assets/css/layout.css
rename to site/assets/css/layout.css
diff --git a/assets/css/lists.css b/site/assets/css/lists.css
similarity index 100%
rename from assets/css/lists.css
rename to site/assets/css/lists.css
diff --git a/assets/css/reset.css b/site/assets/css/reset.css
similarity index 100%
rename from assets/css/reset.css
rename to site/assets/css/reset.css
diff --git a/assets/css/theme.css b/site/assets/css/theme.css
similarity index 100%
rename from assets/css/theme.css
rename to site/assets/css/theme.css
diff --git a/assets/fonts/3dlet.ttf b/site/assets/fonts/3dlet.ttf
similarity index 100%
rename from assets/fonts/3dlet.ttf
rename to site/assets/fonts/3dlet.ttf
diff --git a/assets/fonts/3dlet.txt b/site/assets/fonts/3dlet.txt
similarity index 100%
rename from assets/fonts/3dlet.txt
rename to site/assets/fonts/3dlet.txt
diff --git a/assets/fonts/Adventure Outline.ttf b/site/assets/fonts/Adventure Outline.ttf
similarity index 100%
rename from assets/fonts/Adventure Outline.ttf
rename to site/assets/fonts/Adventure Outline.ttf
diff --git a/assets/fonts/Adventure.ttf b/site/assets/fonts/Adventure.ttf
similarity index 100%
rename from assets/fonts/Adventure.ttf
rename to site/assets/fonts/Adventure.ttf
diff --git a/assets/fonts/Beleren-Bold.ttf b/site/assets/fonts/Beleren-Bold.ttf
similarity index 100%
rename from assets/fonts/Beleren-Bold.ttf
rename to site/assets/fonts/Beleren-Bold.ttf
diff --git a/assets/fonts/Brody Font Regular.otf b/site/assets/fonts/Brody Font Regular.otf
similarity index 100%
rename from assets/fonts/Brody Font Regular.otf
rename to site/assets/fonts/Brody Font Regular.otf
diff --git a/assets/fonts/CollegiateBlackFLF.ttf b/site/assets/fonts/CollegiateBlackFLF.ttf
similarity index 100%
rename from assets/fonts/CollegiateBlackFLF.ttf
rename to site/assets/fonts/CollegiateBlackFLF.ttf
diff --git a/assets/fonts/CollegiateBorderFLF.ttf b/site/assets/fonts/CollegiateBorderFLF.ttf
similarity index 100%
rename from assets/fonts/CollegiateBorderFLF.ttf
rename to site/assets/fonts/CollegiateBorderFLF.ttf
diff --git a/assets/fonts/CollegiateFLF.ttf b/site/assets/fonts/CollegiateFLF.ttf
similarity index 100%
rename from assets/fonts/CollegiateFLF.ttf
rename to site/assets/fonts/CollegiateFLF.ttf
diff --git a/assets/fonts/CollegiateInsideFLF.ttf b/site/assets/fonts/CollegiateInsideFLF.ttf
similarity index 100%
rename from assets/fonts/CollegiateInsideFLF.ttf
rename to site/assets/fonts/CollegiateInsideFLF.ttf
diff --git a/assets/fonts/CollegiateOutlineFLF.ttf b/site/assets/fonts/CollegiateOutlineFLF.ttf
similarity index 100%
rename from assets/fonts/CollegiateOutlineFLF.ttf
rename to site/assets/fonts/CollegiateOutlineFLF.ttf
diff --git a/assets/fonts/EBGaramond.ttf b/site/assets/fonts/EBGaramond.ttf
similarity index 100%
rename from assets/fonts/EBGaramond.ttf
rename to site/assets/fonts/EBGaramond.ttf
diff --git a/assets/fonts/FiraSans-Regular.ttf b/site/assets/fonts/FiraSans-Regular.ttf
similarity index 100%
rename from assets/fonts/FiraSans-Regular.ttf
rename to site/assets/fonts/FiraSans-Regular.ttf
diff --git a/assets/fonts/FloralCapitals.ttf b/site/assets/fonts/FloralCapitals.ttf
similarity index 100%
rename from assets/fonts/FloralCapitals.ttf
rename to site/assets/fonts/FloralCapitals.ttf
diff --git a/assets/fonts/MODERNA_.TTF b/site/assets/fonts/MODERNA_.TTF
similarity index 100%
rename from assets/fonts/MODERNA_.TTF
rename to site/assets/fonts/MODERNA_.TTF
diff --git a/assets/fonts/Open 24 Display St.ttf b/site/assets/fonts/Open 24 Display St.ttf
similarity index 100%
rename from assets/fonts/Open 24 Display St.ttf
rename to site/assets/fonts/Open 24 Display St.ttf
diff --git a/assets/fonts/OxygenMono-Regular.ttf b/site/assets/fonts/OxygenMono-Regular.ttf
similarity index 100%
rename from assets/fonts/OxygenMono-Regular.ttf
rename to site/assets/fonts/OxygenMono-Regular.ttf
diff --git a/assets/fonts/Playbill.ttf b/site/assets/fonts/Playbill.ttf
similarity index 100%
rename from assets/fonts/Playbill.ttf
rename to site/assets/fonts/Playbill.ttf
diff --git a/assets/fonts/PoiretOne-Regular.ttf b/site/assets/fonts/PoiretOne-Regular.ttf
similarity index 100%
rename from assets/fonts/PoiretOne-Regular.ttf
rename to site/assets/fonts/PoiretOne-Regular.ttf
diff --git a/assets/fonts/StitchWarrior demo.ttf b/site/assets/fonts/StitchWarrior demo.ttf
similarity index 100%
rename from assets/fonts/StitchWarrior demo.ttf
rename to site/assets/fonts/StitchWarrior demo.ttf
diff --git a/assets/fonts/electrical.ttf b/site/assets/fonts/electrical.ttf
similarity index 100%
rename from assets/fonts/electrical.ttf
rename to site/assets/fonts/electrical.ttf
diff --git a/assets/js/character_sheet.js b/site/assets/js/character_sheet.js
similarity index 100%
rename from assets/js/character_sheet.js
rename to site/assets/js/character_sheet.js
diff --git a/assets/js/json_scraper.js b/site/assets/js/json_scraper.js
similarity index 100%
rename from assets/js/json_scraper.js
rename to site/assets/js/json_scraper.js
diff --git a/assets/js/lists.js b/site/assets/js/lists.js
similarity index 100%
rename from assets/js/lists.js
rename to site/assets/js/lists.js
diff --git a/assets/js/resize.js b/site/assets/js/resize.js
similarity index 100%
rename from assets/js/resize.js
rename to site/assets/js/resize.js
diff --git a/assets/js/vendor/jquery-3.6.0.min.js b/site/assets/js/vendor/jquery-3.6.0.min.js
similarity index 100%
rename from assets/js/vendor/jquery-3.6.0.min.js
rename to site/assets/js/vendor/jquery-3.6.0.min.js
diff --git a/assets/php/footer.php b/site/assets/php/footer.php
similarity index 100%
rename from assets/php/footer.php
rename to site/assets/php/footer.php
diff --git a/assets/php/nav.php b/site/assets/php/nav.php
similarity index 100%
rename from assets/php/nav.php
rename to site/assets/php/nav.php
diff --git a/assets/php/query_handler.php b/site/assets/php/query_handler.php
similarity index 100%
rename from assets/php/query_handler.php
rename to site/assets/php/query_handler.php
diff --git a/pages/404.html b/site/pages/404.html
similarity index 100%
rename from pages/404.html
rename to site/pages/404.html
diff --git a/pages/about.html b/site/pages/about.html
similarity index 100%
rename from pages/about.html
rename to site/pages/about.html
diff --git a/pages/don-info.html b/site/pages/don-info.html
similarity index 100%
rename from pages/don-info.html
rename to site/pages/don-info.html
diff --git a/pages/home.md b/site/pages/home.md
similarity index 100%
rename from pages/home.md
rename to site/pages/home.md
diff --git a/pages/lists.html b/site/pages/lists.html
similarity index 100%
rename from pages/lists.html
rename to site/pages/lists.html
diff --git a/testbench.ipynb b/testbench.ipynb
index 959d6ea..7d44a2d 100644
--- a/testbench.ipynb
+++ b/testbench.ipynb
@@ -27,7 +27,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 11,
"id": "207d2510",
"metadata": {},
"outputs": [],
@@ -39,6 +39,7 @@
"import subprocess\n",
"import rfeed\n",
"import pydantic\n",
+ "import glob\n",
"from typing import Optional, Union, Literal, BinaryIO, Any\n",
"\n",
"\n",
@@ -49,7 +50,7 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 2,
"id": "4b17a3ed",
"metadata": {},
"outputs": [
@@ -72,24 +73,10 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 3,
"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"
- ]
- }
- ],
+ "outputs": [],
"source": [
"metadata, content = load_markdown('pages/home.md')\n",
"# content = content.replace('src=\"assets', 'src=\"../tmp/dogma-jimfinium/assets')"
@@ -97,20 +84,12 @@
},
{
"cell_type": "code",
- "execution_count": null,
- "id": "0bb15524",
- "metadata": {},
- "outputs": [],
- "source": []
- },
- {
- "cell_type": "code",
- "execution_count": null,
+ "execution_count": 5,
"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",
+ "html = format_html_template('templates/pages/default.html', content = content, metadata = metadata, **PARTIALS)\n",
"with open('dist/home.html', 'w') as f:\n",
" f.write(html)"
]
@@ -151,10 +130,76 @@
},
{
"cell_type": "code",
- "execution_count": null,
+ "execution_count": 12,
+ "id": "dafd924b",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['build/dogma-jimfinium/superlock.md',\n",
+ " 'build/dogma-jimfinium/sustainable-living.md',\n",
+ " 'build/dogma-jimfinium/stocking-up.md',\n",
+ " 'build/dogma-jimfinium/set-up-the-toys.md',\n",
+ " 'build/dogma-jimfinium/babies-love-trash.md',\n",
+ " 'build/dogma-jimfinium/do-what-you-love.md',\n",
+ " 'build/dogma-jimfinium/self-care-is-not-selfish.md',\n",
+ " 'build/dogma-jimfinium/temptation.md',\n",
+ " 'build/dogma-jimfinium/blowouts.md',\n",
+ " 'build/dogma-jimfinium/vitamins.md',\n",
+ " 'build/dogma-jimfinium/gear-for-new-parents.md']"
+ ]
+ },
+ "execution_count": 12,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "glob.glob('build/dogma-jimfinium/*.md')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 13,
+ "id": "cced61c4",
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'gear-for-new-parents.md'"
+ ]
+ },
+ "execution_count": 13,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "os.path.basename( 'build/dogma-jimfinium/gear-for-new-parents.md')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
"id": "944a5efd",
"metadata": {},
- "outputs": [],
+ "outputs": [
+ {
+ "ename": "TypeError",
+ "evalue": "'ArticleMetadata' object is not subscriptable",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
+ "\u001b[31mTypeError\u001b[39m Traceback (most recent call last)",
+ "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[14]\u001b[39m\u001b[32m, line 36\u001b[39m\n\u001b[32m 32\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mopen\u001b[39m(\u001b[33mf\u001b[39m\u001b[33m'\u001b[39m\u001b[33mdist/dogma-jimfinium/\u001b[39m\u001b[38;5;132;01m{\u001b[39;00marticle_filestem\u001b[38;5;132;01m}\u001b[39;00m\u001b[33m.html\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mw\u001b[39m\u001b[33m'\u001b[39m) \u001b[38;5;28;01mas\u001b[39;00m f:\n\u001b[32m 33\u001b[39m f.write(html)\n\u001b[32m---> \u001b[39m\u001b[32m36\u001b[39m index_html = \u001b[43mbuild_blog_archive\u001b[49m\u001b[43m(\u001b[49m\u001b[43mindex\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43m*\u001b[49m\u001b[43m*\u001b[49m\u001b[43mPARTIALS\u001b[49m\u001b[43m)\u001b[49m\n\u001b[32m 37\u001b[39m \u001b[38;5;66;03m# Write the HTML file to /dist/dogma-jimfinium.\u001b[39;00m\n\u001b[32m 38\u001b[39m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mopen\u001b[39m(\u001b[33mf\u001b[39m\u001b[33m'\u001b[39m\u001b[33mdist/dogma-jimfinium/index.html\u001b[39m\u001b[33m'\u001b[39m, \u001b[33m'\u001b[39m\u001b[33mw\u001b[39m\u001b[33m'\u001b[39m) \u001b[38;5;28;01mas\u001b[39;00m f:\n",
+ "\u001b[36mFile \u001b[39m\u001b[32m~/projects/shepich.com/main.py:150\u001b[39m, in \u001b[36mbuild_blog_archive\u001b[39m\u001b[34m(index, page_template, li_template, **kwargs)\u001b[39m\n\u001b[32m 148\u001b[39m \u001b[38;5;66;03m# Add each article as a list item to an unordered list.\u001b[39;00m\n\u001b[32m 149\u001b[39m archive_html_content = \u001b[33m'\u001b[39m\u001b[33m\u001b[39m\u001b[33m'\u001b[39m\n\u001b[32m--> \u001b[39m\u001b[32m150\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m article, (metadata, contents) \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28;43msorted\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43mindex\u001b[49m\u001b[43m.\u001b[49m\u001b[43mitems\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mkey\u001b[49m\u001b[43m \u001b[49m\u001b[43m=\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mlambda\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43mitem\u001b[49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mitem\u001b[49m\u001b[43m[\u001b[49m\u001b[32;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[32;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43mdate\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m)\u001b[49m[::-\u001b[32m1\u001b[39m]:\n\u001b[32m 151\u001b[39m \n\u001b[32m 152\u001b[39m \u001b[38;5;66;03m# Generate HTML for the article (including metadata tags).\u001b[39;00m\n\u001b[32m 153\u001b[39m archive_html_content += format_html_template(\n\u001b[32m 154\u001b[39m li_template,\n\u001b[32m 155\u001b[39m article_filestem = article,\n\u001b[32m (...)\u001b[39m\u001b[32m 158\u001b[39m \n\u001b[32m 159\u001b[39m )\n\u001b[32m 160\u001b[39m archive_html_content +=\u001b[33m'\u001b[39m\u001b[33m
\u001b[39m\u001b[33m'\u001b[39m\n",
+ "\u001b[36mFile \u001b[39m\u001b[32m~/projects/shepich.com/main.py:150\u001b[39m, in \u001b[36mbuild_blog_archive..\u001b[39m\u001b[34m(item)\u001b[39m\n\u001b[32m 148\u001b[39m \u001b[38;5;66;03m# Add each article as a list item to an unordered list.\u001b[39;00m\n\u001b[32m 149\u001b[39m archive_html_content = \u001b[33m'\u001b[39m\u001b[33m\u001b[39m\u001b[33m'\u001b[39m\n\u001b[32m--> \u001b[39m\u001b[32m150\u001b[39m \u001b[38;5;28;01mfor\u001b[39;00m article, (metadata, contents) \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28msorted\u001b[39m(index.items(), key = \u001b[38;5;28;01mlambda\u001b[39;00m item: \u001b[43mitem\u001b[49m\u001b[43m[\u001b[49m\u001b[32;43m1\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[32;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m[\u001b[49m\u001b[33;43m'\u001b[39;49m\u001b[33;43mdate\u001b[39;49m\u001b[33;43m'\u001b[39;49m\u001b[43m]\u001b[49m)[::-\u001b[32m1\u001b[39m]:\n\u001b[32m 151\u001b[39m \n\u001b[32m 152\u001b[39m \u001b[38;5;66;03m# Generate HTML for the article (including metadata tags).\u001b[39;00m\n\u001b[32m 153\u001b[39m archive_html_content += format_html_template(\n\u001b[32m 154\u001b[39m li_template,\n\u001b[32m 155\u001b[39m article_filestem = article,\n\u001b[32m (...)\u001b[39m\u001b[32m 158\u001b[39m \n\u001b[32m 159\u001b[39m )\n\u001b[32m 160\u001b[39m archive_html_content +=\u001b[33m'\u001b[39m\u001b[33m
\u001b[39m\u001b[33m'\u001b[39m\n",
+ "\u001b[31mTypeError\u001b[39m: 'ArticleMetadata' object is not subscriptable"
+ ]
+ }
+ ],
"source": [
"shutil.rmtree('dist/dogma-jimfinium', ignore_errors=True)\n",
"os.makedirs('dist/dogma-jimfinium', exist_ok=True)\n",
@@ -162,14 +207,17 @@
"\n",
"index = {}\n",
"\n",
- "for article in os.listdir('build/dogma-jimfinium'):\n",
- " metadata, content = load_markdown(f'build/dogma-jimfinium/{article}')\n",
+ "for article in glob.glob('build/dogma-jimfinium/*.md'):\n",
+ " metadata, content = load_markdown(article)\n",
+ "\n",
+ " if metadata is None:\n",
+ " print(article)\n",
"\n",
" # Skip unpublished articles.\n",
- " if not metadata.get('published'):\n",
+ " if not metadata.published:\n",
" continue\n",
"\n",
- " article_filestem = os.path.splitext(article)[0]\n",
+ " article_filestem = os.path.splitext(os.path.basename(article))[0]\n",
"\n",
" # Add the article to the index.\n",
" index[article_filestem] = (metadata, content)\n",
@@ -178,8 +226,8 @@
" 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",
+ " blog_tags = ' '.join(format_blog_tags(metadata.tags)),\n",
+ " metadata = metadata\n",
" )\n",
" html = format_html_template('templates/pages/default.html', content = article_html, **PARTIALS)\n",
" \n",
@@ -188,7 +236,7 @@
" f.write(html)\n",
"\n",
"\n",
- "index_html = build_blog_archive(index, metadata.title = 'Dogma Jimfinium | Index', **PARTIALS)\n",
+ "index_html = build_blog_archive(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)"