refactor #1
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,3 +4,4 @@ shepich resume.pdf
|
||||
tmp
|
||||
build
|
||||
dist
|
||||
**/__pycache__
|
||||
Binary file not shown.
30
config.yaml
30
config.yaml
@ -0,0 +1,30 @@
|
||||
author: Jim Shepich III
|
||||
site_defaults:
|
||||
base_url: http://localhost:8000
|
||||
web_root: ./dist
|
||||
templates:
|
||||
partials: ./templates/partials
|
||||
components: ./templates/components
|
||||
pages: ./templates/pages
|
||||
sites:
|
||||
main:
|
||||
build_cache: ./build
|
||||
assets:
|
||||
- ./assets
|
||||
articles:
|
||||
- ./pages/*.md
|
||||
resume:
|
||||
git_repo: ssh://gitea/jim/resume.git
|
||||
build_cache: ./build/resume
|
||||
assets:
|
||||
- '{build_cache}/shepich_resume.pdf'
|
||||
dogma_jimfinium:
|
||||
base_url: http://localhost:8080/dogma-jimfinium
|
||||
git_repo: ssh://gitea/jim/dogma-jimfinium.git
|
||||
build_cache: ./build/dogma-jimfinium
|
||||
web_root: ./dist/dogma-jimfinium
|
||||
assets:
|
||||
- '{build_cache}/assets'
|
||||
articles:
|
||||
- '{build_cache}/*.md'
|
||||
|
||||
71
main.py
71
main.py
@ -2,7 +2,9 @@ import os
|
||||
import subprocess
|
||||
import markdown
|
||||
import yaml
|
||||
from datetime import datetime
|
||||
import pydantic
|
||||
from typing import Optional
|
||||
from datetime import datetime, date
|
||||
|
||||
def filepath_or_string(s: str) -> str:
|
||||
'''Loads the contents of a string if it is a filepath, otherwise returns the string.'''
|
||||
@ -13,15 +15,37 @@ def filepath_or_string(s: str) -> str:
|
||||
return s
|
||||
|
||||
|
||||
def load_markdown(md: str) -> tuple[dict, str]:
|
||||
'''Loads a Markdown file into a (metadata: dict, content: str) pair.'''
|
||||
with open('config.yaml', 'r') as config_file:
|
||||
config = yaml.safe_load(config_file.read())
|
||||
|
||||
class SiteConfig(pydantic.BaseModel):
|
||||
base_url: Optional[str] = config['site_defaults'].get('base_url')
|
||||
git_repo: Optional[str] = config['site_defaults'].get('git_repo')
|
||||
build_cache: Optional[str] = config['site_defaults'].get('build_cache')
|
||||
assets: Optional[list] = config['site_defaults'].get('assets')
|
||||
web_root: Optional[str] = config['site_defaults'].get('web_root')
|
||||
articles: Optional[list] = config['site_defaults'].get('articles')
|
||||
|
||||
class ArticleMetadata(pydantic.BaseModel):
|
||||
title: str
|
||||
author: Optional[str] = config.get('author')
|
||||
date: date
|
||||
lastmod: Optional[date]
|
||||
published: bool
|
||||
tags: list
|
||||
thumbnail: Optional[str] = None
|
||||
|
||||
|
||||
|
||||
def load_markdown(md: str) -> tuple[ArticleMetadata|None, str]:
|
||||
'''Loads a Markdown file into a (metadata: ArticleMetadata, content: str) pair.'''
|
||||
|
||||
# Load the file contents if a filepath is specified, and strip document delimiters ('---').
|
||||
md = filepath_or_string(md).strip().strip('---').strip()
|
||||
|
||||
# If there is no `---` delimiter, then the article has no metadata.
|
||||
if '---' not in md.strip('---'):
|
||||
return {}, md
|
||||
return None, md
|
||||
|
||||
# Split the metadata from the contents.
|
||||
[raw_metadata, raw_article] = md.split('---')
|
||||
@ -32,7 +56,7 @@ def load_markdown(md: str) -> tuple[dict, str]:
|
||||
# Convert the contents to a HTML string.
|
||||
content = markdown.markdown(raw_article)
|
||||
|
||||
return metadata, content
|
||||
return ArticleMetadata(**metadata), content
|
||||
|
||||
|
||||
def format_html_template(template: str, **kwargs) -> str:
|
||||
@ -107,5 +131,42 @@ def format_blog_tags(tags: list[str], template = 'templates/components/blog_tag.
|
||||
format_html_template(template, tag_name = t) for t in tags
|
||||
]
|
||||
|
||||
|
||||
def build_blog_archive(
|
||||
index: dict[str, tuple[str, str]],
|
||||
page_template = 'templates/pages/default.html',
|
||||
li_template = 'templates/components/blog_archive_li.html',
|
||||
**kwargs
|
||||
) -> str:
|
||||
'''Converts an index, formatted as filestem: (metadata, contents) dict,
|
||||
into an HTML page containing the list of articles, sorted from newest to oldest.
|
||||
|
||||
Note: partials must be expanded into the kwargs, as they are needed to generate
|
||||
the overall page.
|
||||
'''
|
||||
|
||||
# Add each article as a list item to an unordered list.
|
||||
archive_html_content = '<ul>'
|
||||
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(
|
||||
li_template,
|
||||
article_filestem = article,
|
||||
blog_tags = ' '.join(format_blog_tags(metadata.tags)),
|
||||
metadata = metadata
|
||||
|
||||
)
|
||||
archive_html_content +='</ul>'
|
||||
|
||||
# Interpolate the article into the overall page template.
|
||||
archive_html_page = format_html_template(
|
||||
page_template,
|
||||
content = archive_html_content,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
return archive_html_page
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
||||
@ -1,8 +0,0 @@
|
||||
<article>
|
||||
<h1>Welcome!</h1>
|
||||
<hr />
|
||||
<p>Welcome to my little corner of the Internet! My name is Jim <span title="'ʃɛpɪk">Shepich</span> (@epicshepich). I like to introduce myself as a jack-of-all-trades with a Master's in data science. My main interests include STEM, martial arts (especially jūjutsu), sci-fi and fantasy, tabletop and video gaming, cartoons and comics, and DIY, but I also love to branch out and learn new things! My dream is to become "The Most Interesting Man in the World."</p>
|
||||
|
||||
<p>This website started as a way for me to exercise and showcase my skills with vanilla HTML, JavaScript, CSS, and PHP. Now, it's just a matter of filling the site with content! My vision for this website is for it to serve as a gift to my future reincarnated self (if that's what happens) — a way to pass on the little tips and tricks, bits of wisdom, resources, and treasures I've accumulated over the course of my life (think <i>new game plus</i>). And if some other kindred spirits find something here that helps them on their journey, that's a bonus! </p>
|
||||
|
||||
<article>
|
||||
10
pages/home.md
Normal file
10
pages/home.md
Normal file
@ -0,0 +1,10 @@
|
||||
---
|
||||
title: Welcome
|
||||
date: 2026-01-30
|
||||
published: true
|
||||
tags: []
|
||||
---
|
||||
|
||||
Welcome to my little corner of the Internet! My name is Jim <span title="'ʃɛpɪk">Shepich</span> (@epicshepich). I like to introduce myself as a jack-of-all-trades with a Master's in data science. My main interests include STEM, martial arts (especially jūjutsu), sci-fi and fantasy, tabletop and video gaming, cartoons and comics, and DIY, but I also love to branch out and learn new things! My dream is to become "The Most Interesting Man in the World."
|
||||
|
||||
This website started as a way for me to exercise and showcase my skills with vanilla HTML, JavaScript, CSS, and PHP. Now, it's just a matter of filling the site with content! My vision for this website is for it to serve as a gift to my future reincarnated self (if that's what happens) — a way to pass on the little tips and tricks, bits of wisdom, resources, and treasures I've accumulated over the course of my life (think _new game plus_). And if some other kindred spirits find something here that helps them on their journey, that's a bonus!
|
||||
@ -1,3 +1,4 @@
|
||||
ipykernel
|
||||
markdown
|
||||
pyyaml
|
||||
rfeed
|
||||
@ -9,11 +9,11 @@
|
||||
<body>
|
||||
<main>
|
||||
<article>
|
||||
<h1 class="headline">{metadata__title}</h1>
|
||||
<h1 class="headline">{metadata.title}</h1>
|
||||
<p class="byline">
|
||||
<address class="author">By <a rel="author" href="mailto:admin@jimlab.io">Jim Shepich III</a></address>
|
||||
<br/>First published: <time pubdate datetime="{metadata__date}">{metadata__date}</time>
|
||||
<br/>Last modified: <time pubdate datetime="{metadata__lastmod}">{metadata__lastmod}</time>
|
||||
<br/>First published: <time pubdate datetime="{metadata.date}">{metadata.date}</time>
|
||||
<br/>Last modified: <time pubdate datetime="{metadata.lastmod}">{metadata.lastmod}</time>
|
||||
</p>
|
||||
{content}
|
||||
</article>
|
||||
|
||||
@ -1 +1 @@
|
||||
<li>{metadata__date} - <a href='{article_filestem}.html'>{metadata__title}</a> {blog_tags}</li>
|
||||
<li>{metadata.date} - <a href='{article_filestem}.html'>{metadata.title}</a> {blog_tags}</li>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<article>
|
||||
<h1 class="headline">{metadata__title}</h1>
|
||||
<h1 class="headline">{metadata.title}</h1>
|
||||
<p class="byline">
|
||||
<address class="author">By <a rel="author" href="mailto:admin@jimlab.io">Jim Shepich III</a></address>
|
||||
<br/>First published: <time pubdate datetime="{metadata__date}">{metadata__date}</time>
|
||||
<br/>Last modified: <time pubdate datetime="{metadata__lastmod}">{metadata__lastmod}</time>
|
||||
<br/>First published: <time pubdate datetime="{metadata.date}">{metadata.date}</time>
|
||||
<br/>Last modified: <time pubdate datetime="{metadata.lastmod}">{metadata.lastmod}</time>
|
||||
</p>
|
||||
{content}
|
||||
<hr />
|
||||
<br /><hr /><br />
|
||||
<p>{blog_tags}</p>
|
||||
</article>
|
||||
14
templates/pages/default.html
Normal file
14
templates/pages/default.html
Normal file
@ -0,0 +1,14 @@
|
||||
<html>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<head>
|
||||
{partials__default_css}
|
||||
{partials__header}
|
||||
{partials__nav}
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
{content}
|
||||
</main>
|
||||
{partials__footer}
|
||||
</body>
|
||||
203
testbench.ipynb
203
testbench.ipynb
@ -27,15 +27,20 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 11,
|
||||
"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",
|
||||
@ -44,24 +49,68 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 12,
|
||||
"id": "d2361c42",
|
||||
"execution_count": null,
|
||||
"id": "4b17a3ed",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"'dist/assets'"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"metadata, content = load_markdown('tmp/dogma-jimfinium/blowouts.md')\n",
|
||||
"content = content.replace('src=\"assets', 'src=\"../tmp/dogma-jimfinium/assets')"
|
||||
"PARTIALS = load_partials()\n",
|
||||
"shutil.rmtree('dist/assets', ignore_errors=True)\n",
|
||||
"shutil.copytree('assets','dist/assets')"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 31,
|
||||
"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": [
|
||||
"PARTIALS = load_partials()\n",
|
||||
"html = format_html_template('templates/blog_post.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.'+k:v for k,v in metadata.items()}, **PARTIALS)\n",
|
||||
"with open('dist/home.html', 'w') as f:\n",
|
||||
" f.write(html)"
|
||||
]
|
||||
@ -102,13 +151,14 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 58,
|
||||
"execution_count": null,
|
||||
"id": "944a5efd",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"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",
|
||||
"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",
|
||||
@ -129,26 +179,122 @@
|
||||
" '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",
|
||||
" **{'metadata.'+k:v for k,v in metadata.items()}\n",
|
||||
" )\n",
|
||||
" html = format_html_template('templates/simple.html', content = article_html, **PARTIALS)\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')\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": [
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
||||
"<rss version=\"2.0\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\"><channel><title>Dogma Jimfinium</title><link>http://localhost:8000/dogma-jimfinium/rss</link><description>Dogma Jimfinium</description><language>en-US</language><lastBuildDate>Thu, 29 Jan 2026 16:29:57 GMT</lastBuildDate><generator>rfeed v1.1.1</generator><docs>https://github.com/svpino/rfeed/blob/master/README.md</docs><item><title>Superlock</title><link>http://localhost:8000/dogma-jimfinium/superlock</link><author>Jim Shepich III</author><pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate><guid isPermaLink=\"true\">superlock</guid></item><item><title>Sustainable Living</title><link>http://localhost:8000/dogma-jimfinium/sustainable-living</link><author>Jim Shepich III</author><pubDate>Thu, 20 Nov 2025 00:00:00 GMT</pubDate><guid isPermaLink=\"true\">sustainable-living</guid></item><item><title>Stocking Up</title><link>http://localhost:8000/dogma-jimfinium/stocking-up</link><author>Jim Shepich III</author><pubDate>Wed, 19 Nov 2025 00:00:00 GMT</pubDate><guid isPermaLink=\"true\">stocking-up</guid></item><item><title>Set Up the Toys</title><link>http://localhost:8000/dogma-jimfinium/set-up-the-toys</link><author>Jim Shepich III</author><pubDate>Wed, 14 Jan 2026 00:00:00 GMT</pubDate><guid isPermaLink=\"true\">set-up-the-toys</guid></item><item><title>Do What You Love</title><link>http://localhost:8000/dogma-jimfinium/do-what-you-love</link><author>Jim Shepich III</author><pubDate>Tue, 10 Jun 2025 00:00:00 GMT</pubDate><guid isPermaLink=\"true\">do-what-you-love</guid></item><item><title>Self-Care is not Selfish</title><link>http://localhost:8000/dogma-jimfinium/self-care-is-not-selfish</link><author>Jim Shepich III</author><pubDate>Sun, 18 May 2025 00:00:00 GMT</pubDate><guid isPermaLink=\"true\">self-care-is-not-selfish</guid></item><item><title>Blowouts</title><link>http://localhost:8000/dogma-jimfinium/blowouts</link><author>Jim Shepich III</author><pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate><guid isPermaLink=\"true\">blowouts</guid></item><item><title>Vitamins & Supplements</title><link>http://localhost:8000/dogma-jimfinium/vitamins</link><author>Jim Shepich III</author><pubDate>Sun, 18 May 2025 00:00:00 GMT</pubDate><guid isPermaLink=\"true\">vitamins</guid></item><item><title>Gear for New Parents</title><link>http://localhost:8000/dogma-jimfinium/gear-for-new-parents</link><author>Jim Shepich III</author><pubDate>Fri, 12 Jul 2024 00:00:00 GMT</pubDate><guid isPermaLink=\"true\">gear-for-new-parents</guid></item></channel></rss>\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": []
|
||||
},
|
||||
@ -159,31 +305,8 @@
|
||||
"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 = '<ul>'\n",
|
||||
" for article, (metadata, contents) in sorted(index.items(), key = lambda item: item[1][0]['date'])[::-1]:\n",
|
||||
" blog_tags = ' '.join(format_blog_tags(metadata['tags']))\n",
|
||||
" index_html_content += format_html_template(\n",
|
||||
" 'templates/components/blog_archive_li.html',\n",
|
||||
" article_filestem = article,\n",
|
||||
" blog_tags = blog_tags,\n",
|
||||
" **{'metadata__'+k:v for k,v in metadata.items()}\n",
|
||||
" \n",
|
||||
" )\n",
|
||||
" index_html_content +='</ul>'\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"
|
||||
"def build_site(site_config: SiteConfig):\n",
|
||||
" "
|
||||
]
|
||||
}
|
||||
],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user