refactor #1

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

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ tmp
build
dist
**/__pycache__
custom.yaml

View File

@ -17,7 +17,8 @@ sites:
title: Resume
base_url: http://localhost:8000
web_root: ./dist
git_repo: ssh://gitea/jim/resume.git
git_repo:
url: ssh://gitea/jim/resume.git
build_cache: ./build/resume
assets:
- 'shepich_resume.pdf'
@ -26,7 +27,9 @@ sites:
title: Dogma Jimfinium
description: May it bolster the skills of all who read it.
base_url: http://localhost:8000/dogma-jimfinium
git_repo: ssh://gitea/jim/dogma-jimfinium.git
git_repo:
url: ssh://gitea/jim/dogma-jimfinium.git
branch: pub
build_cache: ./build/dogma-jimfinium
web_root: ./dist/dogma-jimfinium
assets:

View File

@ -1,13 +1,5 @@
import os
import re
import glob
import shutil
import subprocess
import markdown
import yaml
import pydantic
from typing import Optional
from datetime import datetime, date
from dotmap import DotMap
import logging
@ -21,13 +13,8 @@ from .articles import ArticleMetadata, load_markdown, build_articles, build_inde
from .blog import build_blog_archive, build_rss_feed
def build_site(site: SiteConfig, templates: DotMap):
'''The pipeline for building a site defined in config.yaml.'''
logger.info(f'Building site "{site.title}".')
@ -74,9 +61,11 @@ def build_site(site: SiteConfig, templates: DotMap):
else:
logger.debug('Addon "rss" not elected.')
def main():
def build(config_filepath = './config.yaml'):
'''Pipeline for building the entire website, including all sites defined in config.yaml.'''
logger.info('Loading config.')
with open('./config.yaml', 'r') as config_file:
with open(config_filepath, 'r') as config_file:
config = yaml.safe_load(config_file.read())
logger.info('Loading global templates.')
@ -85,6 +74,5 @@ def main():
for site in config['sites'].values():
build_site(SiteConfig(**site), templates)
if __name__ == '__main__':
main()

15
jimsite/__main__.py Normal file
View File

@ -0,0 +1,15 @@
import argparse
from jimsite import build
if __name__ == '__main__':
parser = argparse.ArgumentParser(
prog='Jimsite',
description='A Python-based templating engine for building static websites from Markdown documents.',
epilog='Gonna be a hot one!'
)
parser.add_argument('-c', '--config', type=str, default='config.yaml', help='Specifies the path to a YAML config file; defaults to config.yaml in the CWD.')
args = parser.parse_args()
build(config_filepath = args.config)

View File

@ -11,6 +11,7 @@ from .common import filepath_or_string, SiteConfig
from .templating import format_html_template, TemplateSelections
class ArticleMetadata(pydantic.BaseModel):
'''A model for the YAML frontmatter included with Markdown articles.'''
title: str
date: date
published: bool
@ -21,6 +22,8 @@ class ArticleMetadata(pydantic.BaseModel):
description: Optional[str] = None
class Article(pydantic.BaseModel):
'''A model for a Markdown article, including its YAML frontmatter
metadata, as well as its path relative to the build cache root.'''
path: str
content: str
metadata: Optional[ArticleMetadata] = None

View File

@ -1,20 +1,30 @@
import os
import glob
import shutil
from .common import run, SiteConfig
from .common import run, GitRepo, SiteConfig
# TODO: Add support for origin and branch.
def pull_git_repo(repo: str, build_cache: str) -> None:
def pull_git_repo(repo: GitRepo, build_cache: str) -> None:
'''Pulls/clones a repo into the build cache directory.'''
# If a repo exists in the build cache, pull to it.
if os.path.exists(f'{build_cache}/.git'):
run(f'git -C {build_cache} pull origin')
# If a branch is specified, check out to it.
if repo.branch is not None:
run(f"git checkout {repo.branch}")
run(f"git -C {build_cache} pull {repo.remote}{' '+repo.branch if repo.branch else ''}")
# If the build cache is empty, clone the repo into it.
else:
run(f'git clone {repo} {build_cache}')
run(f"git clone {repo.url}{(' -b '+repo.branch) if repo.branch else ''} -o {repo.remote} {build_cache}")
def copy_assets(site: SiteConfig):
'''Copies the list of site assets from the build cache to the web root.'''
def copy_assets(site: SiteConfig) -> None:
'''Copies the list of site assets from the build cache to the web root.
The asset list can include globs (*). All paths are resolved relative to
the build cache root, and will be copied to an analogous location in the
web root.'''
# Expand any globbed expressions.
expanded_asset_list = []
@ -28,7 +38,7 @@ def copy_assets(site: SiteConfig):
# 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("/")}'
destination = f'{site.web_root}/What the program does{a.lstrip("/")}'
# Delete existing files.
shutil.rmtree(destination, ignore_errors=True)

View File

@ -25,6 +25,11 @@ class GlobalVars(pydantic.BaseModel):
'''Static-valued global variables to be interpolated into any HTML templates.'''
today: date = datetime.today()
class GitRepo(pydantic.BaseModel):
'''A nested model used in SiteConfig to represent a Git repo.'''
url: str
branch: Optional[str] = None
remote: Optional[str] = 'origin'
class SiteConfig(pydantic.BaseModel):
base_url: str
@ -33,7 +38,7 @@ class SiteConfig(pydantic.BaseModel):
title: str
description: Optional[str] = None
published: Optional[bool] = True
git_repo: Optional[str] = None
git_repo: Optional[GitRepo] = None
assets: Optional[list] = None
articles: Optional[list] = None
template_selections: Optional[dict] = {}

View File

@ -6,5 +6,7 @@
<br />
<h2>Post History</h2>
{content}
<br /><hr /><br />
<p>Last Updated: {globalvars.today}<span>{templates.components.rss_icon}</span></p>
</article>
<script src="/assets/js/blog_archive_query.js"></script>