Added Jimoire Laboratoire

This commit is contained in:
Jim Shepich III 2026-02-08 11:42:53 -05:00
parent 8b4af3f35b
commit cabcda5b00
10 changed files with 53 additions and 33 deletions

View File

@ -9,7 +9,7 @@ sites:
assets: assets:
- /assets - /assets
articles: articles:
- ./pages/*.md - '*.md'
template_selections: template_selections:
article: templates.components.simple_article article: templates.components.simple_article
@ -50,6 +50,20 @@ sites:
addons: addons:
- rss - rss
# TODO: add Jimoire Laboratoire jimoire_laboratoire:
title: Jimoire Laboratoire
description: How I built the Jimlab, and you can too!
base_url: http://localhost:8000/jimoire-laboratoire
git_repo:
url: ssh://gitea/jimlab/jimoire-laboratoire.git
branch: jimsite
lfs: false
build_cache: ./build/jimoire-laboratoire
web_root: ./dist/jimoire-laboratoire
assets: []
articles:
- '*.md'
- 'essentials/*.md'
- '**/*.md'
# TODO: add newsletter # TODO: add newsletter

View File

@ -3,6 +3,7 @@ import glob
import yaml import yaml
import markdown import markdown
import pydantic import pydantic
import logging
from typing import Optional, Union from typing import Optional, Union
from dotmap import DotMap from dotmap import DotMap
from datetime import date from datetime import date
@ -10,12 +11,14 @@ from datetime import date
from .common import filepath_or_string, SiteConfig from .common import filepath_or_string, SiteConfig
from .templating import format_html_template, TemplateSelections from .templating import format_html_template, TemplateSelections
logger = logging.getLogger(__name__)
class ArticleMetadata(pydantic.BaseModel): class ArticleMetadata(pydantic.BaseModel):
'''A model for the YAML frontmatter included with Markdown articles.''' '''A model for the YAML frontmatter included with Markdown articles.'''
title: str title: str
date: date date: date
published: bool tags: Optional[list] = []
tags: list published: Optional[bool] = False
author: Optional[str] = None author: Optional[str] = None
lastmod: Optional[date] = None lastmod: Optional[date] = None
thumbnail: Optional[str] = None thumbnail: Optional[str] = None
@ -41,6 +44,8 @@ def load_markdown(md: str) -> tuple[Optional[ArticleMetadata], str]:
# Split the metadata from the contents. # Split the metadata from the contents.
[raw_metadata, raw_article] = md.split('---') [raw_metadata, raw_article] = md.split('---')
# TODO: Consider adding an optional postscript document, for things like unescaped CSS.
# Use YAML to parse the metadata. # Use YAML to parse the metadata.
metadata = yaml.safe_load(raw_metadata) metadata = yaml.safe_load(raw_metadata)
@ -66,21 +71,23 @@ def build_index(site: SiteConfig) -> dict[str, Article]:
) )
for article_full_path in expanded_article_list: for article_full_path in set(expanded_article_list):
logger.debug(f'Loading article from {article_full_path}')
metadata, content = load_markdown(article_full_path) metadata, content = load_markdown(article_full_path)
# TODO: consider adding support for articles with no metadata
if metadata is None:
logger.debug(f'Article loaded from {article_full_path} has no metadata. Skipping.')
continue
# Skip unpublished articles. # Skip unpublished articles.
if not metadata.published: if not metadata.published:
logger.debug(f'Article loaded from {article_full_path} is not published. Skipping.')
continue continue
# Construct the article's path for the index by discarding the build cache # Construct the article's path for the index by discarding the build cache.
# and replacing .md with .html. article_path = article_full_path.removeprefix(site.build_cache).lstrip("/").replace('.md','.html')
# article_path = article_full_path\
# .removeprefix(site.build_cache)\
# .lstrip('/')\
# .replace('.md','.html')
# TODO: add tolerance for a hierarchical article directory structure.
article_path = os.path.basename(article_full_path).replace('.md', '.html')
index[article_path] = Article( index[article_path] = Article(
path = article_path, path = article_path,
@ -147,7 +154,14 @@ def build_articles(
) )
with open(f"{site.web_root.rstrip('/')}/{article.path}", 'w') as f: # Construct the path to which the article page is to be saved.
destination = f"{site.web_root.rstrip('/')}/{article.path}"
# Ensure the directory structure exists.
os.makedirs(os.path.dirname(destination), exist_ok=True)
# Save the file.
with open(destination, 'w') as f:
f.write(page_html) f.write(page_html)

View File

@ -1,8 +1,10 @@
import os import os
import glob import glob
import shutil import shutil
import logging
from .common import run, GitRepo, SiteConfig from .common import run, GitRepo, SiteConfig
logger = logging.getLogger(__name__)
def pull_git_repo(repo: GitRepo, build_cache: str) -> None: def pull_git_repo(repo: GitRepo, build_cache: str) -> None:
'''Pulls/clones a repo into the build cache directory.''' '''Pulls/clones a repo into the build cache directory.'''
@ -49,7 +51,7 @@ def copy_assets(site: SiteConfig) -> None:
glob.glob(f'{site.build_cache}/{a.lstrip("/")}') glob.glob(f'{site.build_cache}/{a.lstrip("/")}')
) )
for asset in expanded_asset_list: for asset in set(expanded_asset_list):
# Skip ignored assets. # Skip ignored assets.
if asset in ignored_asset_list: if asset in ignored_asset_list:

View File

@ -292,4 +292,8 @@ p.socials{
filter: brightness(0) saturate(100%) invert(95%) sepia(100%) saturate(14%) hue-rotate(213deg) brightness(104%) contrast(104%); filter: brightness(0) saturate(100%) invert(95%) sepia(100%) saturate(14%) hue-rotate(213deg) brightness(104%) contrast(104%);
margin-left: 0.25em; margin-left: 0.25em;
margin-right:0.25em; margin-right:0.25em;
}
article ul, article ol{
margin-bottom: 1em;
} }

View File

@ -1,9 +0,0 @@
<article>
<h1>404 Error</h1>
<hr />
<span id="404-message"></span>
<script>
var query_page = $("[name='query_page']")[0].innerHTML;
document.getElementById("404-message").innerHTML="Page '"+query_page+"' not found.";
</script>
</article>

View File

@ -1,6 +0,0 @@
<article>
<h1>About</h1>
<hr />
Coming soon!
</article>

View File

@ -12,9 +12,9 @@
{article.content} {article.content}
<br /><hr /><br /> <br /><hr /><br />
<p> <p>
<a href="{previous_article.path}" title="{previous_article.metadata.title}" data="{previous_article.path}" class="previous-article-link">&lt; Previous</a> <a href="{site.base_url}/{previous_article.path}" title="{previous_article.metadata.title}" data="{previous_article.path}" class="previous-article-link">&lt; Previous</a>
&nbsp; <!-- This non-breaking space prevents the RSS icon from getting weird when previous-article-link is hidden. --> &nbsp; <!-- This non-breaking space prevents the RSS icon from getting weird when previous-article-link is hidden. -->
<a href="{next_article.path}" title="{next_article.metadata.title}" data="{next_article.path}" class="next-article-link">Next &gt;</a> <a href="{site.base_url}/{next_article.path}" title="{next_article.metadata.title}" data="{next_article.path}" class="next-article-link">Next &gt;</a>
</p> </p>
<p>Tags: {blog_tags}{templates.components.rss_icon}</p> <p>Tags: {blog_tags}{templates.components.rss_icon}</p>
</article> </article>

View File

@ -1,5 +1,4 @@
<footer> <footer>
<!-- Add socials (email, Matrix, Friendica, Gitea)-->
<p class="socials"> <p class="socials">
<a class="social" href="https://matrix.to/#/@jim:jimlab.io" title="Matrix"><img src="/assets/img/matrix.svg" alt="Matrix logo"></a> <a class="social" href="https://matrix.to/#/@jim:jimlab.io" title="Matrix"><img src="/assets/img/matrix.svg" alt="Matrix logo"></a>
<a class="social" href="https://friendica.jimlab.io/profile/jim/profile" title="Friendica"><img src="/assets/img/friendica.svg" alt="Friendica logo"></a> <a class="social" href="https://friendica.jimlab.io/profile/jim/profile" title="Friendica"><img src="/assets/img/friendica.svg" alt="Friendica logo"></a>
@ -7,4 +6,5 @@
<a class="social" href="mailto:admin@jimlab.io" title="eMail"><img src="/assets/img/email.svg" alt="eMail logo"></a> <a class="social" href="mailto:admin@jimlab.io" title="eMail"><img src="/assets/img/email.svg" alt="eMail logo"></a>
</span> </span>
<br /><p class='copyright'>Copyright &copy; 2021-{globalvars.today.year} Jim Shepich</span> <br /><p class='copyright'>Copyright &copy; 2021-{globalvars.today.year} Jim Shepich</span>
<!-- TODO: Add licenses for 3rd party content (e.g. logos) -->
</footer> </footer>

View File

@ -2,4 +2,5 @@
<a href='/index.html' target='_self'><div class='nav-tab'><span class='nav-text'>Home</span></div></a> <a href='/index.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/archive.html' target='_self'><div class='nav-tab'><span class='nav-text'>Dogma Jimfinium</span></div></a> <a href='/dogma-jimfinium/archive.html' target='_self'><div class='nav-tab'><span class='nav-text'>Dogma Jimfinium</span></div></a>
<a href='/jimoire-laboratoire/index.html' target='_self'><div class='nav-tab'><span class='nav-text'>Jimoire Laboratoire</span></div></a>
</nav> </nav>