Compare commits

...

3 Commits

Author SHA1 Message Date
555c2e767a make images 2023-03-13 22:25:42 +00:00
e0382bfc81 make html 2023-03-13 22:25:17 +00:00
00dae2c336 make rss 2023-03-12 23:22:07 +00:00
4 changed files with 251 additions and 5 deletions

59
build/index.py Normal file
View File

@ -0,0 +1,59 @@
#!/usr/bin/env python3
import sys
import re
# we expect the arguments to be filepaths to each blog post
def print_usage():
print("\nusage: python mkblogindex.py POSTS\n")
print("\n")
print("\t\tPOSTS\tfilepaths of blog posts")
# check args for at least one file path
if len(sys.argv) < 2:
print_usage()
sys.exit(1)
# posts are arguments from index 1 onwards
posts = sys.argv[1:]
dir_pattern = re.compile("(.+)/(blog\/.+\.html)")
path_pattern = re.compile("(.+)\/(\d{4})\/(\d{1,2})\/(\d{1,2})\/(.+).html")
title_pattern = re.compile("<h1>(.+)</h1>")
# filter posts to just those with a date in them
posts = [p for p in posts if path_pattern.match(p)]
posts.reverse()
links = []
# for each file we want to output an <a> tag with a relative href to the site root
for path in posts:
m = re.match(path_pattern, path)
year = m.group(2)
month = m.group(3).rjust(2, '0')
day = m.group(4).rjust(2, '0')
date = f'<span class="post-date">{year}-{month}-{day}</span>'
title = ""
with open(path) as f:
for line in f:
if title_pattern.match(line):
title = re.sub(title_pattern, r'<span class="post-title">\1</span>', line).strip()
break
# clean leading directories to get the relative path we'll use for the link
url = re.sub(dir_pattern, r"\2", path)
item = (date, f'<li><a href="{url}">{date}{title}</a></li>')
links.append(item)
# make sure we're properly ordered in reverse date order lol
links = sorted(links, key=lambda x: x[0])
links.reverse()
for l in links:
print(l[1])

88
build/page.py Normal file
View File

@ -0,0 +1,88 @@
#!/usr/bin/env python
import os
import sys
import markdown
import re
# SRC
# +-2022/
# | +-10/
# | +-12/
# | +-25/
# +-2023/
# | +-1/
# | +-26/
# | +-3/
# ...
def print_usage():
print("\nusage: python mkblog.py SRC DEST\n")
print("\n")
print("\t\tSRC\tinput markdown file")
print("\t\tDEST\tdestination html file")
# check args
if len(sys.argv) != 3:
print_usage()
sys.exit(1)
src_file = sys.argv[1]
dest_file = sys.argv[2]
# check blog root exists
if not os.path.isfile(src_file):
print("{blog_root} doesn't exist")
sys.exit(1)
# make dest dir if it doesnt exist
dest_dir = os.path.dirname(dest_file)
print(dest_dir)
if not os.path.isdir(dest_dir):
os.makedirs(dest_dir)
# write markdown into a dummy file first so that we can add lines before it in the final output
dummy_file = f"{dest_file}.bak"
open(dummy_file, 'w').close()
print(f"{src_file} -> {dummy_file}")
markdown.markdownFromFile(input=src_file, output=dummy_file, extensions=["fenced_code"])
# TODO: a lot of this templating work is specific to the ktyl.dev blog - ideally, that stuff should
# be in *that* repo, not this one
print(f"{dummy_file} -> {dest_file}")
with open(dummy_file, 'r') as read_file, open(dest_file, 'w') as write_file:
write_file.write("#include blogstart.html\n")
# modify the basic html to make it nicer for styling later
html = read_file.read()
# extract images from their enclosing <p> tags and put them in img panels
html = re.sub('(<p>(<img(?:.+)/>)</p>)', r'<div class="img-panel">\2</div>', html)
# insert text-panel start between non-<p> and <p> elements
html = re.sub('((?<!</p>)\n)(<p>)', r'\1<div class="text-panel">\n\2', html)
# insert para-block end between <p> and non-<p> elements
html = re.sub('(</p>\n)((?!<p>))', r'\1</div>\n\2', html)
# insert code-panel start before <pre> elements
html = re.sub('(<pre>)', r'<div class="code-panel">\n\1', html)
# insert code-panel end after </pre> elements
html = re.sub('(</pre>)', r'\1\n</div>', html)
# replace horizontal rules with nice separator dot
html = re.sub('<hr />', r'<div class="separator"></div>', html)
lines = html.split("\n")
# tack on a closing div because we will have opened one without closing it on the final <p>
lines.append("</div>")
for line in lines:
write_file.write(line + "\n")
write_file.write("\n#include blogend.html\n")
os.remove(dummy_file)

76
build/rss.py Normal file
View File

@ -0,0 +1,76 @@
#!/usr/bin/env python3
import markdown
import pathlib
import sys
import re
def print_usage():
print("\nusage: python mkblogrss.py POSTS\n")
print("\n")
print("\t\tPOSTS\tfilepaths of blog posts")
# check args for at least one file path
if len(sys.argv) < 2:
print_usage()
sys.exit(1)
# posts are arguments from index 1 onwards
posts = sys.argv[1:]
# header and footer to enclose feed items
header = """<?xml version="1.0" encoding="utf-8" ?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
<channel>
<title>ktyl.dev</title>
<link>https://ktyl.dev/blog/index.html</link>
<description>mostly computer stuff!</description>
<atom:link href="https://ktyl.dev/blog/index.xml" rel="self" type="application/rss+xml"/>
"""
footer = "</channel></rss>"
# regex patterns
title_pattern = re.compile("<h1>(.+)</h1>")
path_pattern = re.compile("(.+)\/(\d{4})\/(\d{1,2})\/(\d{1,2})\/(.+).md")
def make_item(path):
str = "<item>\n"
# get the HTML version of the file
text = ""
with open(path) as f:
text = f.read()
html = markdown.markdown(text, extensions=["fenced_code"])
# title
title = ""
m = title_pattern.match(html)
title = m.group(1)
str += f"<title>{title}</title>\n"
# link
url = "/".join(pathlib.Path(path).parts[2:])
url = url.replace(".md", ".html")
link = f"https://ktyl.dev/blog/{url}"
str += f"<link>{link}</link>\n"
# content
description = html
description = re.sub('<', '&lt;', description)
description = re.sub('>', '&gt;', description)
str += f"<description>{description}</description>\n"
# pub date
date = re.sub(path_pattern, r'\2-\3-\4', path)
str += f"<pubDate>{date}</pubDate>\n"
str += "</item>"
return str
# print everything!
print(header)
for p in posts:
print(make_item(p))
print(footer)

View File

@ -3,21 +3,44 @@ OUT_DIR = out/
HTML_DIR = $(OUT_DIR)html
GEMINI_DIR = $(OUT_DIR)gemini
MAKE_GEMINI = build/markdown2gemini.py
MAKE_HTML = build/markdown2html.py
MAKE_GEMINI = build/markdown2gemini.py
MAKE_HTML = build/page.py
MAKE_RSS = build/rss.py
MAKE_HTML_INDEX = build/index.py
PAGES = $(shell find $(SRC_DIR) -wholename "$(BLOG_SRC_DIR)*.md")
HTML_TARGETS = $(PAGES:$(SRC_DIR)/%.md=$(HTML_DIR)/%.html)
HTML_RSS = $(HTML_DIR)/index.xml
HTML_INDEX = $(HTML_DIR)/index.html
GEMINI_TARGETS = $(PAGES:$(SRC_DIR)/%.md=$(GEMINI_DIR)/%.gmi)
IMAGES = $(shell find $(SRC_DIR) -wholename "$(SRC_DIR)*.png" -o -wholename "$(SRC_DIR)*.jpg")
PNG_TARGETS = $(IMAGES:$(SRC_DIR)/%.png=$(HTML_DIR)/%.png)
JPG_TARGETS = $(IMAGES:$(SRC_DIR)/%.jpg=$(HTML_DIR)/%.jpg)
IMAGE_TARGETS = $(PNG_TARGETS) $(JPG_TARGETS)
_dummy := $(shell mkdir -p $(HTML_DIR) $(GEMINI_DIR))
$(HTML_DIR)/%.html: $(SRC_DIR)/%.md
python $(MAKE_HTML) $< $@
pipenv run python $(MAKE_HTML) $< $@
html: $(HTML_TARGETS)
echo $(HTML_TARGETS)
$(HTML_RSS): $(PAGES)
pipenv run python $(MAKE_RSS) $(PAGES) > $@
$(HTML_INDEX): $(HTML_TARGETS)
pipenv run python $(MAKE_HTML_INDEX) $(HTML_TARGETS) > $@
$(HTML_DIR)/%.png: $(SRC_DIR)/%.png
mkdir -p $(shell dirname $@)
cp $< $@
$(HTML_DIR)/%.jpg: $(SRC_DIR)/%.jpg
mkdir -p $(shell dirname $@)
cp $< $@
html: $(HTML_TARGETS) $(HTML_RSS) $(HTML_INDEX) $(IMAGE_TARGETS)
gemini: