Added blog archive

This commit is contained in:
Jim Shepich III 2026-01-29 10:09:32 -05:00
parent 8b38b3e86d
commit 006aeab2c1
10 changed files with 180 additions and 24 deletions

View File

@ -145,3 +145,31 @@ summary.heading{
-webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-tap-highlight-color: rgba(0,0,0,0);
-webkit-tap-highlight-color: transparent; -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;
}

32
main.py
View File

@ -77,3 +77,35 @@ def load_partials() -> dict:
current_year = datetime.now().year current_year = datetime.now().year
) )
return partials 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

View File

@ -1,5 +1,4 @@
<html> <html>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<head> <head>
@ -7,9 +6,8 @@
{partials__header} {partials__header}
{partials__nav} {partials__nav}
</head> </head>
<body> <body>
<main>
<article> <article>
<h1 class="headline">{metadata__title}</h1> <h1 class="headline">{metadata__title}</h1>
<p class="byline"> <p class="byline">
@ -19,5 +17,6 @@
</p> </p>
{content} {content}
</article> </article>
</main>
{partials__footer} {partials__footer}
</body> </body>

View File

@ -0,0 +1 @@
<li>{metadata__date} - <a href='{article_filestem}.html'>{metadata__title}</a> {blog_tags}</li>

View File

@ -0,0 +1,11 @@
<article>
<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>
</p>
{content}
<hr />
<p>{blog_tags}</p>
</article>

View File

@ -0,0 +1 @@
<a href='tags/{tag_name}.html'><span class='blog-tag'>{tag_name}</span></a>

View File

@ -1,4 +1,5 @@
<nav id="main-navbar" class="no-highlight"> <nav id="main-navbar" class="no-highlight">
<a href='/home.html' target='_self'><div class='nav-tab'><span class='nav-text'>Home</span></div></a> <a href='/home.html' target='_self'><div class='nav-tab'><span class='nav-text'>Home</span></div></a>
<a href='/shepich_resume.pdf' target='blank'><div class='nav-tab'><span class='nav-text'>Resume</span></div></a> <a href='/shepich_resume.pdf' target='_blank'><div class='nav-tab'><span class='nav-text'>Resume</span></div></a>
<a href='/dogma-jimfinium/index.html' target='_self'><div class='nav-tab'><span class='nav-text'>Dogma Jimfinium</span></div></a>
</nav> </nav>

14
templates/simple.html Normal file
View 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>

View File

@ -11,7 +11,7 @@
"- [] Determine static website structure\n", "- [] Determine static website structure\n",
" - Where to put assets for subsites like dogma jimfinium\n", " - Where to put assets for subsites like dogma jimfinium\n",
" - How to otherwise organize pages\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", "- [] Consider separating article templates and overall page templates\n",
"- [] RSS feed\n", "- [] RSS feed\n",
"\n", "\n",
@ -27,7 +27,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 11,
"id": "207d2510", "id": "207d2510",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@ -44,7 +44,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 9, "execution_count": 12,
"id": "d2361c42", "id": "d2361c42",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
@ -55,13 +55,13 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 10, "execution_count": 31,
"id": "ed7b3b2f", "id": "ed7b3b2f",
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"PARTIALS = load_partials()\n", "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", "with open('dist/home.html', 'w') as f:\n",
" f.write(html)" " f.write(html)"
] ]
@ -98,23 +98,92 @@
"output_type": "execute_result" "output_type": "execute_result"
} }
], ],
"source": []
},
{
"cell_type": "code",
"execution_count": 58,
"id": "944a5efd",
"metadata": {},
"outputs": [],
"source": [ "source": [
"def get_latest_resume():\n", "run(f'rm -rf dist/dogma-jimfinium && mkdir -p dist/dogma-jimfinium')\n",
" max_date = '0000-00-00'\n", "run(f'cp -r build/dogma-jimfinium/assets dist/dogma-jimfinium')\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",
"\n", "\n",
" print(max_date)\n", "index = {}\n",
" # print(max_date.strftime('%Y-%m-%d'))\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", " \n",
" run(f'cp build/resume/{max_date}/shepich_resume.pdf dist/shepich_resume.pdf')" " # 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 = '<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"
] ]
} }
], ],