refactor #1

Merged
jim merged 20 commits from refactor into main 2026-02-03 01:08:46 -05:00
13 changed files with 267 additions and 27 deletions
Showing only changes of commit 8b38b3e86d - Show all commits

7
.gitignore vendored
View File

@ -1 +1,6 @@
shepich resume.pdf
shepich resume.pdf
**/.venv
**/.env
tmp
build
dist

Binary file not shown.

View File

@ -1,21 +0,0 @@
## Pages
- Home
- About
- CV
- Everything in as much detail as possible
- Projects
- E&E
- M|Chroma
- SI-Formatter
- Socials (maybe better as a footer)
- Instagram
- Facebook
- LinkedIn
- GitHub
- MAL
- Bookmarks (?)
## Reference Material
- https://www.tomscott.com/
- http://vihart.com/
- https://www.singingbanana.com/

View File

@ -1,5 +0,0 @@
<?php
phpinfo();
?>

79
main.py Normal file
View File

@ -0,0 +1,79 @@
import os
import subprocess
import markdown
import yaml
from datetime import datetime
def filepath_or_string(s: str) -> str:
'''Loads the contents of a string if it is a filepath, otherwise returns the string.'''
if os.path.isfile(s):
with open(s, 'r') as f:
return f.read()
else:
return s
def load_markdown(md: str) -> tuple[dict, str]:
'''Loads a Markdown file into a (metadata: dict, 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
# Split the metadata from the contents.
[raw_metadata, raw_article] = md.split('---')
# Use YAML to parse the metadata.
metadata = yaml.safe_load(raw_metadata)
# Convert the contents to a HTML string.
content = markdown.markdown(raw_article)
return metadata, content
def format_html_template(template: str, **kwargs) -> str:
'''Interpolates variables specified as keyword arguments
into the given HTML template.'''
# Load the template if a filepath is given.
template = filepath_or_string(template)
# Interpolate the kwargs into the HTML template.
html = template.format(**kwargs)
# Return the formatted HTML.
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 load_partials() -> dict:
"""Loads partial templates from the templates/partials directory."""
partials = {}
for filename in os.listdir('templates/partials'):
with open(f'templates/partials/{filename}') as partial_file:
partial_template = partial_file.read()
partials[f'partials__{os.path.splitext(filename)[0]}'] = format_html_template(
partial_template,
current_year = datetime.now().year
)
return partials

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
ipykernel
markdown
pyyaml

23
templates/default.html Normal file
View File

@ -0,0 +1,23 @@
<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>
<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}
</article>
{partials__footer}
</body>

View File

View File

@ -0,0 +1,4 @@
<link rel="stylesheet" type="text/css" href="/assets/css/reset.css">
<link rel="stylesheet" type="text/css" href="/assets/css/common.css">
<link rel="stylesheet" type="text/css" href="/assets/css/layout.css">
<link rel="stylesheet" type="text/css" href="/assets/css/theme.css">

View File

@ -0,0 +1,3 @@
<footer>
<br /><span class='copyright'>Copyright &copy; 2021-{current_year} Jim Shepich</span>
</footer>

View File

@ -0,0 +1,3 @@
<header id="main-header" class="no-highlight">
<span class="silver-text">Jimlab</span>
</header>

View File

@ -0,0 +1,4 @@
<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='/shepich_resume.pdf' target='blank'><div class='nav-tab'><span class='nav-text'>Resume</span></div></a>
</nav>

142
testbench.ipynb Normal file
View File

@ -0,0 +1,142 @@
{
"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",
"- [] 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": 1,
"id": "207d2510",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"import markdown\n",
"import yaml\n",
"import subprocess\n",
"\n",
"\n",
"from datetime import datetime\n",
"from main import *"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "d2361c42",
"metadata": {},
"outputs": [],
"source": [
"metadata, content = load_markdown('tmp/dogma-jimfinium/blowouts.md')\n",
"content = content.replace('src=\"assets', 'src=\"../tmp/dogma-jimfinium/assets')"
]
},
{
"cell_type": "code",
"execution_count": 10,
"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",
"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": [
"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",
"\n",
" print(max_date)\n",
" # print(max_date.strftime('%Y-%m-%d'))\n",
" \n",
" run(f'cp build/resume/{max_date}/shepich_resume.pdf dist/shepich_resume.pdf')"
]
}
],
"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
}