refactor #1
@ -1,4 +1,5 @@
|
|||||||
author: Jim Shepich III
|
author: Jim Shepich III
|
||||||
|
templates_folder: ./templates
|
||||||
site_defaults:
|
site_defaults:
|
||||||
base_url: http://localhost:8000
|
base_url: http://localhost:8000
|
||||||
web_root: ./dist
|
web_root: ./dist
|
||||||
|
|||||||
@ -7,6 +7,12 @@ import yaml
|
|||||||
import pydantic
|
import pydantic
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
|
from dotmap import DotMap
|
||||||
|
|
||||||
|
class GlobalVars(pydantic.BaseModel):
|
||||||
|
'''Static-valued global variables to be interpolated into any HTML templates.'''
|
||||||
|
today: date = datetime.today()
|
||||||
|
|
||||||
|
|
||||||
def filepath_or_string(s: str) -> str:
|
def filepath_or_string(s: str) -> str:
|
||||||
'''Loads the contents of a string if it is a filepath, otherwise returns the string.'''
|
'''Loads the contents of a string if it is a filepath, otherwise returns the string.'''
|
||||||
@ -69,7 +75,11 @@ def format_html_template(template: str, **kwargs) -> str:
|
|||||||
template = filepath_or_string(template)
|
template = filepath_or_string(template)
|
||||||
|
|
||||||
# Interpolate the kwargs into the HTML template.
|
# Interpolate the kwargs into the HTML template.
|
||||||
html = template.format(**kwargs)
|
# Apply global variables twice in case a partial used
|
||||||
|
# by the first call of .format() uses a variable.
|
||||||
|
html = template.format(
|
||||||
|
globalvars = GlobalVars(), **kwargs
|
||||||
|
).format(globalvars = GlobalVars())
|
||||||
|
|
||||||
# Return the formatted HTML.
|
# Return the formatted HTML.
|
||||||
return html
|
return html
|
||||||
@ -91,7 +101,7 @@ def load_partials() -> dict:
|
|||||||
with open(f'templates/partials/{filename}') as partial_file:
|
with open(f'templates/partials/{filename}') as partial_file:
|
||||||
partial_template = partial_file.read()
|
partial_template = partial_file.read()
|
||||||
|
|
||||||
partials[f'partials__{os.path.splitext(filename)[0]}'] = format_html_template(
|
partials[f'partials.{os.path.splitext(filename)[0]}'] = format_html_template(
|
||||||
partial_template,
|
partial_template,
|
||||||
current_year = datetime.now().year
|
current_year = datetime.now().year
|
||||||
)
|
)
|
||||||
@ -193,5 +203,74 @@ def copy_assets(site: SiteConfig):
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def build_index(site: SiteConfig) -> dict:
|
||||||
|
'''Loads the sites articles into an index mapping the filename stem
|
||||||
|
to a (metadata: dict, content: str) tuple.'''
|
||||||
|
|
||||||
|
index = {}
|
||||||
|
|
||||||
|
# Expand any globbed expressions.
|
||||||
|
expanded_article_list = []
|
||||||
|
for a in site.articles:
|
||||||
|
expanded_article_list.extend(
|
||||||
|
# Article paths are defined relative to the build cache; construct the full path.
|
||||||
|
glob.glob(f'{site.build_cache}/{a.lstrip("/")}')
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
for article in expanded_article_list:
|
||||||
|
metadata, content = load_markdown(article)
|
||||||
|
|
||||||
|
# Skip unpublished articles.
|
||||||
|
if not metadata.published:
|
||||||
|
continue
|
||||||
|
|
||||||
|
article_filestem = os.path.splitext(os.path.basename(article))[0]
|
||||||
|
index[article_filestem] = (metadata, content)
|
||||||
|
|
||||||
|
return index
|
||||||
|
|
||||||
|
|
||||||
|
def map_templates(dir: str, parent = '') -> DotMap:
|
||||||
|
'''Recursively maps the templates directory into a nested dict structure.
|
||||||
|
Leaves map the filestems of .html template files to their contents.
|
||||||
|
'''
|
||||||
|
|
||||||
|
output = {}
|
||||||
|
|
||||||
|
# List the files and subdirectories at the top level.
|
||||||
|
for sub in os.listdir(os.path.join(parent,dir)):
|
||||||
|
|
||||||
|
# Construct the full path to the file or subdir from the root of the tree.
|
||||||
|
full_path = os.path.join(parent,dir,sub)
|
||||||
|
|
||||||
|
# Recursively map subdirectories.
|
||||||
|
if os.path.isdir(full_path):
|
||||||
|
output[sub] = map_templates(sub, parent = dir)
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Templates must be .html files.
|
||||||
|
filestem, ext = os.path.splitext(sub)
|
||||||
|
if ext != '.html':
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Load template file.
|
||||||
|
with open(full_path, 'r') as file:
|
||||||
|
html = file.read()
|
||||||
|
|
||||||
|
# # Interpolate global variables into partials.
|
||||||
|
# if 'partials' in full_path:
|
||||||
|
# html = html.format(globalvars = GlobalVars())
|
||||||
|
|
||||||
|
output[filestem] = html
|
||||||
|
|
||||||
|
return DotMap(output)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@ -1,4 +1,5 @@
|
|||||||
ipykernel
|
ipykernel
|
||||||
markdown
|
markdown
|
||||||
pyyaml
|
pyyaml
|
||||||
rfeed
|
rfeed
|
||||||
|
dotmap
|
||||||
@ -8,6 +8,7 @@
|
|||||||
/*https://www.schemecolor.com/light-silver-gradient.php)*/
|
/*https://www.schemecolor.com/light-silver-gradient.php)*/
|
||||||
--navy-blue:#091b75;
|
--navy-blue:#091b75;
|
||||||
--azure:#4f67db;
|
--azure:#4f67db;
|
||||||
|
--azure-tint-20: #6e87e5;
|
||||||
--charcoal:#333333;
|
--charcoal:#333333;
|
||||||
font-size:120%;
|
font-size:120%;
|
||||||
|
|
||||||
@ -22,47 +23,47 @@
|
|||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Beleren;
|
font-family: Beleren;
|
||||||
src: url('fonts/Beleren-Bold.ttf');
|
src: url('/assets/fonts/Beleren-Bold.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Playbill;
|
font-family: Playbill;
|
||||||
src: url('fonts/Playbill.ttf');
|
src: url('/assets/fonts/Playbill.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Moderna;
|
font-family: Moderna;
|
||||||
src: url('fonts/MODERNA_.ttf');
|
src: url('/assets/fonts/MODERNA_.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Adventure;
|
font-family: Adventure;
|
||||||
src: url('fonts/Adventure.ttf');
|
src: url('/assets/fonts/Adventure.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Oxygen;
|
font-family: Oxygen;
|
||||||
src: url('fonts/OxygenMono-Regular.ttf');
|
src: url('/assets/fonts/OxygenMono-Regular.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Garamond;
|
font-family: Garamond;
|
||||||
src: url('fonts/EBGaramond.ttf');
|
src: url('/assets/fonts/EBGaramond.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Fira;
|
font-family: Fira;
|
||||||
src: url('fonts/FiraSans-Regular.ttf');
|
src: url('/assets/fonts/FiraSans-Regular.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: StitchWarrior;
|
font-family: StitchWarrior;
|
||||||
src: url('fonts/StitchWarrior demo.ttf');
|
src: url('/assets/fonts/StitchWarrior demo.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Floral;
|
font-family: Floral;
|
||||||
src: url('fonts/FloralCapitals.ttf');
|
src: url('/assets/fonts/FloralCapitals.ttf');
|
||||||
}
|
}
|
||||||
|
|
||||||
var{
|
var{
|
||||||
|
|||||||
@ -2,9 +2,9 @@
|
|||||||
<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>
|
||||||
{partials__default_css}
|
{partials.default_css}
|
||||||
{partials__header}
|
{partials.header}
|
||||||
{partials__nav}
|
{partials.nav}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
@ -18,5 +18,5 @@
|
|||||||
{content}
|
{content}
|
||||||
</article>
|
</article>
|
||||||
</main>
|
</main>
|
||||||
{partials__footer}
|
{partials.footer}
|
||||||
</body>
|
</body>
|
||||||
@ -2,13 +2,13 @@
|
|||||||
<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>
|
||||||
{partials__default_css}
|
{partials.default_css}
|
||||||
{partials__header}
|
{partials.header}
|
||||||
{partials__nav}
|
{partials.nav}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
{content}
|
{content}
|
||||||
</main>
|
</main>
|
||||||
{partials__footer}
|
{partials.footer}
|
||||||
</body>
|
</body>
|
||||||
@ -1,3 +1,3 @@
|
|||||||
<footer>
|
<footer>
|
||||||
<br /><span class='copyright'>Copyright © 2021-{current_year} Jim Shepich</span>
|
<br /><span class='copyright'>Copyright © 2021-{globalvars.today.year} Jim Shepich</span>
|
||||||
</footer>
|
</footer>
|
||||||
@ -2,13 +2,13 @@
|
|||||||
<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>
|
||||||
{partials__default_css}
|
{partials.default_css}
|
||||||
{partials__header}
|
{partials.header}
|
||||||
{partials__nav}
|
{partials.nav}
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
{content}
|
{content}
|
||||||
</main>
|
</main>
|
||||||
{partials__footer}
|
{partials.footer}
|
||||||
</body>
|
</body>
|
||||||
553
testbench.ipynb
553
testbench.ipynb
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user