# BENZIN Makefile
include config.mk
# Directories
SRC ?= src
TEMPLATES ?= templates
OUT ?= out
# User supplied variables
WEBSITE_URL ?= https://example.com
WEBSITE_TITLE ?= Example Website
CONVERT ?= pandoc --from=gfm+emoji --to=html --section-divs --shift-heading-level-by=1
EMOJI_SIZE ?= 20
EMOJI_STYLE ?= margin-bottom: -4px;
BLOG_PREVIEW_MARKER ?= Recent blog posts
# File locations
PAGE_TEMPLATE ?= templates/page.html
OPENRING_TEMPLATE ?= templates/openring.html
RSS_TEMPLATE ?= templates/rss.xml
RSS_ITEM_TEMPLATE ?= templates/rss_item.xml
OPENRING_URLS ?= src/urls
RSS ?= out/blog/index.xml
# Sources
BLOG_SOURCES=$(wildcard src/blog/*.md)
EMOJI_SOURCES=$(wildcard src/public/emoji/*)
PUBLIC_SOURCES=$(shell find src/public -type f)
SOURCES=$(shell find src -type f -name "*.md")
# Outputs
TMP_HTML=$(patsubst src/%.md, tmp/%.content.html, $(SOURCES))
HTML=$(patsubst src/%.md, out/%.html, $(SOURCES))
OPENRING_FOOTER=$(patsubst templates/%, tmp/%, $(OPENRING_TEMPLATE))
BLOG_XML=$(patsubst src/%.md, tmp/%.xml, $(filter-out src/blog/index.md, $(BLOG_SOURCES)))
PUBLIC=$(patsubst src/%, out/%, $(PUBLIC_SOURCES))
.PHONY: clean all serve
.SECONDARY: $(TMP_HTML) $(BLOG_XML)
all: $(HTML) $(RSS) $(PUBLIC)
# Standalone HTML
out/%.html: tmp/%.content.html tmp/%.meta.title tmp/%.meta.description $(PAGE_TEMPLATE) $(OPENRING_FOOTER)
@mkdir -p $(@D)
sed "/<\/main>/e cat $< $(OPENRING_FOOTER)" $(PAGE_TEMPLATE) > $@
sed -i \
-e '/
/{' \
-e 'a ' -e "r tmp/$*.meta.title" -e "a | $(WEBSITE_TITLE) <\/title>" \
-e 'a ' \
-e '}' $@
out/index.html: tmp/index.content.html $(PAGE_TEMPLATE)
@mkdir -p $(@D)
sed "/<\/main>/e cat $<" $(PAGE_TEMPLATE) > $@
sed -i \
-e '//{' \
-e "a $(WEBSITE_TITLE)<\/title>" \
-e '}' $@
# Embeddable HTML
tmp/%.content.html: src/%.md tmp/emoji.sed
@mkdir -p $(@D)
sed -e "s/.md)/.html)/g" -f tmp/emoji.sed $< | $(CONVERT) > $@
tmp/index.content.html: src/index.md tmp/emoji.sed tmp/blog/preview.md
@mkdir -p $(@D)
sed -e "/$(BLOG_PREVIEW_MARKER)/r tmp/blog/preview.md" $< \
| sed -e "s/.md)/.html)/g" -f tmp/emoji.sed \
| $(CONVERT) > $@
# Metadata (TODO: parse YAML front matter)
tmp/%.meta.title: src/%.md
@mkdir -p $(@D)
sed '/^#/q' $< | sed 's/#* //; s/:.*://;' > $@
tmp/%.meta.description: src/%.md
@mkdir -p $(@D)
sed '2,/^$$/!d' $< > $@
tmp/blog/%.meta.date: src/blog/%.md
@mkdir -p $(@D)
@date --rfc-email -d $* > $@
# Emoji sed script
tmp/emoji.sed: $(EMOJI_SOURCES)
@mkdir -p $(@D)
for emoji in $^; do\
basename=$$(basename $$emoji); \
name=$${basename%.*}; \
echo "s|:$${name}:||g;" >> $@; \
done
# Blog preview
tmp/blog/preview.md: src/blog/index.md
@mkdir -p $(@D)
sed -n "s/^-/ -/; s|(|(blog/| ; /^ -/p" $< | head -n 4 > $@
# RSS
$(RSS): $(BLOG_XML) $(RSS_TEMPLATE)
@mkdir -p $(@D)
sed "/<\/channel>/e cat $(BLOG_XML)" $(RSS_TEMPLATE) > $@
sed -i \
-e '//{' \
-e "a $(WEBSITE_TITLE)<\/title>" \
-e "a $(WEBSITE_URL)<\/link>" \
-e "a $$(date --rfc-email)<\/lastPubDate>" \
-e '}' $@
tmp/%.xml: tmp/%.content.html tmp/%.meta.title tmp/%.meta.date $(RSS_ITEM_TEMPLATE)
@mkdir -p $(@D)
sed "/CDATA/r $<" $(RSS_ITEM_TEMPLATE) > $@
sed -i \
-e '/- /{' \
-e 'a ' -e "r tmp/$*.meta.title" -e 'a <\/title>' \
-e 'a ' -e "r tmp/$*.meta.date" -e 'a <\/pubDate>' \
-e "a $(WEBSITE_URL)/$*.html<\/link>" \
-e '}' $@
# Openring
$(OPENRING_FOOTER): $(OPENRING_TEMPLATE) $(OPENRING_URLS)
@mkdir -p $(@D)
openring $$(sed '/^#/d; s/^/-s /' $(OPENRING_URLS)) < $< > $@
# Assets
out/public/%: src/public/%
@mkdir -p $(@D)
@cp $^ $@
out/public/emoji/%.png: src/public/emoji/%.png
@mkdir -p $(@D)
convert $< -resize $(EMOJI_SIZE)x$(EMOJI_SIZE) $@
# Management
serve: $(HTML)
quark -h 127.0.0.1 -p 8000 -d out -l
clean:
rm -rf tmp out/*