summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile476
-rw-r--r--deps.mk468
-rw-r--r--meta.capim6
-rwxr-xr-xmkdeps.sh7
4 files changed, 488 insertions, 469 deletions
diff --git a/Makefile b/Makefile
index 007eb43..4cf6689 100644
--- a/Makefile
+++ b/Makefile
@@ -2,486 +2,24 @@
DATE = 1970-01-01
VERSION = 0.1.0
NAME = papo.im
-NAME_UC = $(NAME)
LANGUAGES = en
-## Installation prefix. Defaults to "/usr".
-PREFIX = /usr
-BINDIR = $(PREFIX)/bin
-LIBDIR = $(PREFIX)/lib
-INCLUDEDIR = $(PREFIX)/include
-SRCDIR = $(PREFIX)/src/$(NAME)
-SHAREDIR = $(PREFIX)/share
-LOCALEDIR = $(SHAREDIR)/locale
-MANDIR = $(SHAREDIR)/man
-DOCDIR = $(SHAREDIR)/doc/$(NAME)
-HTMLDIR = $(SHAREDIR)/html/$(NAME)
-EXEC = ./
-## Where to store the installation. Empty by default.
-DESTDIR =
-LDLIBS =
-PUBURL = public.asc.txt
-FFMFLAGS = -y -hide_banner -loglevel warning
-BASEURL = /
-
-
-
-.SUFFIXES:
-.SUFFIXES: .adoc .conf .snippets .indexentry .feedentry .mapentry .sortdata .xml
-.SUFFIXES: .htmlbody .htmlheader .htmlfooter .htmllisting .html .links .caslinks
-.SUFFIXES: .txt .categorydata .gz .torrent .flac .ogg .ps .pdf .sentinel
-
-.adoc.conf:
- mkwb conf src/global.conf $< > $@
-
-.adoc.htmlbody:
- mkwb htmlbody $< > $@
-
-.htmlbody.html:
- mkwb html $< > $@
-
-.conf.htmlheader:
- mkwb html -H $< > $@
-
-.conf.htmlfooter:
- mkwb html -F $< > $@
-
-.adoc.snippets:
- mkwb snippets $< > $@
-
-.conf.indexentry:
- mkwb indexentry $< > $@
-
-.htmlbody.feedentry:
- mkwb feedentry $< > $@
-
-.conf.mapentry:
- mkwb mapentry $< > $@
-
-.conf.sortdata:
- mkwb sortdata $< > $@
-
-.conf.categorydata:
- mkwb categorydata $< > $@
-
-.adoc.links:
- mkwb links $< > $@
-
-.links.caslinks:
- grep -Ev '^(link|image):' $< | xargs -I_ sh -c '\
- printf "%s\n" "_" | sha256sum | \
- printf "%s\t%s\n" "`cut -d" " -f1`" "_"' > $@
-
-.flac.ogg:
- ffmpeg $(FFMFLAGS) -i $< -ar 48000 -vn -c:a libvorbis -b:a 320k $@
-
-.adoc.ps:
- eslaides < $< > $@
-
-.ps.pdf:
- ps2pdf - < $< > $@
-
+PORT = 3333
+## `all:` anchors the default target before deps.mk's first rule
+## would otherwise claim it. deps.mk ends with `include` of mkwb's
+## site.mk, so the canonical rules load transitively.
all:
include deps.mk
-listings.adoc = $(categories.adoc) $(indexes.adoc)
-sources.adoc = $(articles.adoc) $(listings.adoc) $(pages.adoc)
-sources.htmlbody = $(sources.adoc:.adoc=.htmlbody)
-sources.html = $(sources.adoc:.adoc=.html)
-sources.snippets = $(sources.adoc:.adoc=.snippets)
-sources.snippets.gz = $(sources.adoc:.adoc=.snippets.gz)
-sources.conf = $(sources.adoc:.adoc=.conf)
-sources.links = $(sources.adoc:.adoc=.links)
-sources.caslinks = $(sources.adoc:.adoc=.caslinks)
-sources.mapentry = $(sources.adoc:.adoc=.mapentry)
-articles.indexentry = $(articles.adoc:.adoc=.indexentry)
-articles.feedentry = $(articles.adoc:.adoc=.feedentry)
-articles.sortdata = $(articles.adoc:.adoc=.sortdata)
-articles.categorydata = $(articles.adoc:.adoc=.categorydata)
-listings.htmlheader = $(listings.adoc:.adoc=.htmlheader)
-listings.htmlfooter = $(listings.adoc:.adoc=.htmlfooter)
-listings.html = $(listings.adoc:.adoc=.html)
-indexes.htmllisting = $(indexes.adoc:.adoc=.htmllisting)
-categories.htmllisting = $(categories.adoc:.adoc=.htmllisting)
-categories.txt = $(categories.adoc:.adoc=.txt)
-categories.xml = $(categories.adoc:.adoc=.xml)
-categories.xml.gz = $(categories.adoc:.adoc=.xml.gz)
-sources.media.torrent = $(sources.media:=.torrent)
-slides.ps = $(slides.adoc:.adoc=.ps)
-slides.pdf = $(slides.adoc:.adoc=.pdf)
-
-sources = \
- $(sources.adoc) \
- $(sources.extras) \
- $(images.svg) \
- src/content/favicon.ico \
- src/content/favicon.png \
- src/content/style.css \
- src/content/$(PUBURL) \
-
-dynamic-contents = \
- $(sources.html) \
- $(slides.pdf) \
- $(feeds.xml) \
- $(sources.media.torrent) \
- src/content/sitemap.xml \
-
-static-contents = \
- $(sources.extras) \
- $(images.svg) \
- src/content/favicon.ico \
- src/content/favicon.png \
- src/content/style.css \
- src/content/$(PUBURL) \
- src/content/.well-known/security.txt \
-
-dynamic-contents.gz = $(dynamic-contents:=.gz)
-
-static-contents.gz = \
- $(images.svg:=.gz) \
- src/content/favicon.ico.gz \
- src/content/style.css.gz \
- src/content/$(PUBURL).gz \
- src/content/.well-known/security.txt.gz \
-
-contents.gz = \
- $(dynamic-contents.gz) \
- $(static-contents.gz) \
-
-contents = \
- $(dynamic-contents) \
- $(static-contents) \
-
-all-filelists = \
- $(sources.snippets) \
- $(sources.snippets.gz) \
- $(categories.xml) \
- $(categories.xml.gz) \
-
-all-contents = \
- $(contents) \
- $(contents.gz) \
-
-captured-assets = \
- src/content/$(PUBURL) \
- src/content/favicon.ico \
- src/content/favicon.png \
-
-captured-assets.sentinel = $(captured-assets:=.sentinel)
-
-
-derived-assets = \
- $(dynamic-contents) \
- $(contents.gz) \
- $(sources.html) \
- $(sources.htmlbody) \
- $(sources.snippets) \
- $(sources.snippets.gz) \
- $(sources.conf) \
- $(sources.links) \
- $(sources.caslinks) \
- $(sources.mapentry) \
- src/dyn.conf \
- src/base.conf \
- src/global.conf \
- $(articles.indexentry) \
- $(articles.feedentry) \
- $(articles.sortdata) \
- $(articles.categorydata) \
- $(listings.htmlheader) \
- $(listings.htmlfooter) \
- $(listings.html) \
- $(indexes.htmllisting) \
- $(categories.htmllisting) \
- $(categories.txt) \
- $(categories.xml) \
- $(categories.xml.gz) \
- $(slides.ps) \
- $(slides.pdf) \
- email.txt \
- baseurl.txt \
- fingerprint.txt \
- expiry.txt \
- expiry-epoch.txt \
- now.txt \
- src/content/.well-known/security.txt \
- src/all-contents.txt \
- src/all-filelists.txt \
- src/all-symlinks.txt \
- src/install.txt \
- src/sort-expected.txt \
- src/sort-given.txt \
- src/sources.txt \
- install.txt \
- sources.txt \
- src/content/.gitignore \
- $(captured-assets.sentinel) \
-
-side-assets = \
- src/collections/*/*/*/*/*/*.html.*.txt \
- src/collections/*/*/*/*/*/*.txt.gz \
- src/collections/*/*/index.html.*.txt \
- src/collections/*/*/sortdata.txt \
- src/collections/*/*/feed.*.xml \
- src/collections/*/*/feed.*.xml.gz \
- src/collections/*/*/*.sortdata \
- src/pages/*/*.html.*.txt \
- src/content/.well-known/ \
- `cat src/all-symlinks.txt 2>/dev/null` \
- `cat src/linkonly-dirs.txt 2>/dev/null` \
-
-
-
-## Default target. Builds all artifacts required for testing
-## and installation.
-all: $(derived-assets)
-all: $(captured-assets)
-
-
-$(derived-assets): Makefile deps.mk
-$(sources.conf): src/global.conf
-
-
-src/content/.gitignore: src/symlinks.txt
- cd src/content/ && mkwb symlinks ../symlinks.txt > $(@F)
-
-src/dyn.conf: email.txt baseurl.txt fingerprint.txt
- printf "export url_pre='%s'\n" "`cat baseurl.txt`" > $@
- printf "export email='%s'\n" "`cat email.txt`" >> $@
- printf "export publickey='%s'\n" "`cat fingerprint.txt`" >> $@
- printf "export publickey_url='$(PUBURL)'\n" >> $@
- printf 'export sourcecode_url="$$url_pre/git/$(NAME)"\n' >> $@
-
-src/base.conf: src/dyn.conf src/static.conf
- cat src/dyn.conf src/static.conf > $@
-
-src/global.conf: src/base.conf
- mkwb conf -G src/base.conf > $@
-
-$(listings.html):
- cat $*.htmlheader $*.htmlbody $*.htmllisting $*.htmlfooter > $@
-
-$(indexes.htmllisting):
- mkwb indexbody $*.conf > $@
-
-$(categories.htmllisting):
- mkwb categoriesbody $*.conf > $@
-
-$(categories.txt): src/global.conf
- mkwb categories src/global.conf $(@D) > $@
-
-$(categories.xml):
- for f in `cat $*.txt`; do \
- c="`printf '%s\n' "$$f" | cut -d. -f2`"; \
- mkwb feed src/global.conf "$$f" > $(@D)/feed."$$c".xml; \
- printf '%s\n' $(@D)/feed."$$c".xml; \
- done > $@
-
-$(feeds.xml):
- mkwb feed src/global.conf $(@D)/sortdata.txt > $@
-
-$(contents.gz):
- gzip -9fk $*
- touch $@
-
-$(sources.snippets.gz) $(categories.xml.gz):
- if [ -s $* ]; then gzip -9fk `cat $*`; fi
- sed 's/$$/.gz/' $* > $@
-
-src/content/$(PUBURL).gz: src/content/$(PUBURL).sentinel
-src/content/$(PUBURL).sentinel: email.txt
- gpg --export --armour "`cat email.txt`" | ifne ifnew $*
- touch $@
-
-src/content/favicon.ico.gz: src/content/favicon.ico.sentinel
-src/content/favicon.ico.sentinel: src/content/img/favicon.svg
- convert src/content/img/favicon.svg -strip ico:- | ifnew $*
- touch $@
-
-src/content/favicon.png.sentinel: src/content/img/favicon.svg
- convert src/content/img/favicon.svg -strip png:- | ifnew $*
- touch $@
-
-$(sources.media.torrent):
- F="`printf '%s\n' $* | cut -d/ -f3-`" && \
- mktorrent -xfd -n $(*F) -o $@ -w "https://$(NAME)$(BASEURL)$${F}" $*
-
-src/content/sitemap.xml.gz: src/content/sitemap.xml
-src/content/sitemap.xml: $(sources.mapentry)
- mkwb sitemap $(sources.mapentry) > $@
-
-email.txt: meta.capim
- cat meta.capim | awk '$$1 == ":email" && $$0=$$2' | tr -d '"' > $@
-
-baseurl.txt: meta.capim
- cat meta.capim | awk '$$1 == ":baseurl" && $$0=$$2' | tr -d '"' > $@
-
-fingerprint.txt: src/content/$(PUBURL)
- gpg --always-trust --no-keyring --show-key --with-colons \
- src/content/$(PUBURL) | \
- awk -F: '/^pub:/ { print $$5 }' > $@
-
-expiry.txt: src/content/$(PUBURL)
- gpg --always-trust --no-keyring --show-key --with-colons \
- src/content/$(PUBURL) | \
- awk -F: '/^pub:/ { print $$7 }' | \
- xargs -I% date -Is -d@% > $@
-
-expiry-epoch.txt: expiry.txt
- date -d "`cat expiry.txt`" '+%s' > $@
-
-now.txt:
- now > $@
-
-src/content/.well-known/security.txt.gz: src/content/.well-known/security.txt
-src/content/.well-known/security.txt: email.txt baseurl.txt expiry.txt
- mkdir -p $(@D)
- printf 'Contact: mailto:%s\n' "`cat email.txt`" > $@
- printf 'Expires: %s\n' "`cat expiry.txt`" >> $@
- printf 'Encryption: %s/$(PUBURL)\n' "`cat baseurl.txt`" >> $@
- printf 'Preferred-Languages: en, pt, fr, eo, es, de\n' >> $@
-
-src/sources.txt:
- printf '%s\n' $(sources) > $@
-
-src/all-contents.txt:
- printf '%s\n' $(all-contents) > $@
-
-src/all-filelists.txt: src/all-symlinks.txt
- printf '%s\n' $(all-filelists) src/all-symlinks.txt > $@
-
-src/all-symlinks.txt: src/content/.gitignore
- sed 's|^|src/content|' src/content/.gitignore > $@
-
-src/install.txt: src/all-contents.txt src/all-filelists.txt $(all-filelists)
- cat src/all-contents.txt `cat src/all-filelists.txt` > $@
-
-sources.txt: src/sources.txt
-install.txt: src/install.txt
-sources.txt install.txt:
- sed 's|^src/content/||' src/$(@F) > $@
-
-
-
-src/sort-expected.txt:
- dirname $(articles.adoc) | env LANG=POSIX.UTF-8 sort | uniq -c | \
- awk '{ printf "%s\t%s\n", $$2, $$1 }' > $@
-
-src/sort-given.txt: $(sources.conf) src/sort-expected.txt
- awk '{ \
- "grep \"^export sort=\" " $$1 "/*.conf | wc -l" | getline cnt; \
- printf "%s\t%s\n", $$1, cnt; \
- }' src/sort-expected.txt > $@
-
-check-unit-sorting: src/sort-expected.txt src/sort-given.txt
- diff -U10 src/sort-expected.txt src/sort-given.txt
-
-
-.SUFFIXES: .updatedat-check
-sources.updatedat-check = $(sources.adoc:.adoc=.updatedat-check)
-$(sources.updatedat-check):
- . ./$*.conf && if [ -n "$$updatedat_epoch" ] && \
- [ "$$updatedat_epoch" -le "$$date_epoch" ]; then exit 3; fi
-
-check-unit-updatedat: $(sources.updatedat-check)
-
-
-.SUFFIXES: .links-internal-check
-sources.links-internal-check = $(sources.adoc:.adoc=.links-internal-check)
-$(sources.links-internal-check): $(sources.html) $(slides.pdf)
- grep -E '^(link|image):' $*.links | cut -d: -f2- | \
- xargs -I% test -e $(*D)/%
-
-check-unit-links-internal: $(sources.links-internal-check)
-
-
-check-unit-links-external:
-
-
-symlink-deps = \
- $(sources.html) \
- $(feeds.xml) \
- $(categories.xml) \
- src/content/.well-known/security.txt \
- $(sources.media.torrent) \
-
-check-unit-links-symlinks: src/all-symlinks.txt $(symlink-deps)
- find `cat src/all-symlinks.txt` | xargs -n1 test -e
-
-
-check-unit-links: check-unit-links-internal check-unit-links-external
-check-unit-links: check-unit-links-symlinks
-
-
-MAXSIZE = 52428800 # from spec: https://www.sitemaps.org/protocol.html
-check-unit-sitemap-size: src/content/sitemap.xml
- test "`stat --printf='%s' src/content/sitemap.xml`" -le $(MAXSIZE)
-
-check-unit-sitemap-count: src/content/sitemap.xml
- test "`grep -cF '</url>' src/content/sitemap.xml`" -le 50000
-
-check-unit-sitemap: check-unit-sitemap-count check-unit-sitemap-size
-
-
-check-unit-expiry: expiry-epoch.txt now.txt
- test "`cat expiry-epoch.txt`" -gt "`cat now.txt`"
-
-
-check-unit: check-unit-sorting check-unit-updatedat check-unit-links
-check-unit: check-unit-sitemap check-unit-expiry
-
-
-integration-tests = \
-
-.PRECIOUS: $(integration-tests)
-$(integration-tests): ALWAYS
- sh $@
-
-check-integration: $(integration-tests)
-
-
-## Run all tests. Each test suite is isolated, so that a parallel
-## build can run tests at the same time. The required artifacts
-## are created if missing.
-check: check-unit check-integration
-
-
+## ---- per-site additions to the canonical rules ----------------
i18n:
po4a po/po4a.cfg
-
-
-## Remove *all* derived artifacts produced during the build.
-## A dedicated test asserts that this is always true.
-clean:
- rm -rf $(derived-assets) $(side-assets)
-
-
-## Installs into $(DESTDIR)$(PREFIX). Its dependency target
-## ensures that all installable artifacts are crafted beforehand.
-install: all
- rsync --mkpath -a --files-from=install.txt src/content/ \
- '$(DESTDIR)$(HTMLDIR)'
- rsync --mkpath -a --files-from=sources.txt src/content/ \
- '$(DESTDIR)$(SRCDIR)'
-
-## Uninstalls from $(DESTDIR)$(PREFIX). This is a perfect mirror
-## of the "install" target, and removes *all* that was installed.
-## A dedicated test asserts that this is always true.
-uninstall:
- rm -rf \
- '$(DESTDIR)$(SRCDIR)' \
- '$(DESTDIR)$(HTMLDIR)' \
-
-
-
-PORT = 3333
-## Run file server for local installed static files.
+## Run file server for the installed static files.
run:
serve -n -p $(PORT) -d '$(DESTDIR)$(HTMLDIR)'
-
-ALWAYS:
+$(derived-assets): Makefile deps.mk
diff --git a/deps.mk b/deps.mk
index dcb63ef..7861e51 100644
--- a/deps.mk
+++ b/deps.mk
@@ -220,3 +220,471 @@ src/content/en/incidents/categories.txt: $(articles.en.incidents.categorydata)
src/content/en/incidents/categories.txt src/content/en/incidents/feed.xml: $(articles.en.incidents.feedentry)
src/content/en/incidents/categories.htmllisting src/content/en/incidents/categories.xml: src/content/en/incidents/categories.txt
src/content/en/incidents/categories.xml.gz: src/content/en/incidents/categories.xml
+
+## mkwb canonical site rules. Sites consume this content by
+## inlining it at the end of their generated deps.mk: mkdeps.sh
+## runs `mkwb rules` (which cats this file) so deps.mk ends up
+## self-contained -- no make-time `include` of an external file.
+## The site Makefile only needs an `all:` anchor followed by
+## `include deps.mk`. Order matters: `all:` must come first
+## (otherwise deps.mk's first target becomes the default), and
+## the canonical rules below must follow deps.mk's variable
+## assignments so that `all: $(derived-assets)` can resolve its
+## prereq list at parse time.
+##
+## The including Makefile is expected to define at minimum:
+##
+## NAME -- site name (used for SRCDIR/HTMLDIR install paths)
+## VERSION
+## DATE
+##
+## To override any of PREFIX / BINDIR / SHAREDIR / SRCDIR /
+## HTMLDIR / PUBURL / BASEURL / FFMFLAGS, set them AFTER the
+## include (plain `=`, POSIX -- no `?=` conditional assignment),
+## or pass `-e` to make to let env vars take precedence.
+
+
+
+## Default values. Sites override AFTER the include or via env.
+PREFIX = /usr
+BINDIR = $(PREFIX)/bin
+LIBDIR = $(PREFIX)/lib
+INCLUDEDIR = $(PREFIX)/include
+SHAREDIR = $(PREFIX)/share
+LOCALEDIR = $(SHAREDIR)/locale
+MANDIR = $(SHAREDIR)/man
+DOCDIR = $(SHAREDIR)/doc/$(NAME)
+HTMLDIR = $(SHAREDIR)/html/$(NAME)
+SRCDIR = $(PREFIX)/src/$(NAME)
+DESTDIR =
+PUBURL = public.asc.txt
+BASEURL = /
+FFMFLAGS = -y -hide_banner -loglevel warning
+
+
+
+.SUFFIXES:
+.SUFFIXES: .adoc .conf .snippets .indexentry .feedentry .mapentry .sortdata .xml
+.SUFFIXES: .htmlbody .htmlheader .htmlfooter .htmllisting .html .links .caslinks
+.SUFFIXES: .txt .categorydata .gz .torrent .flac .ogg .ps .pdf .sentinel
+
+.adoc.conf:
+ mkwb conf src/global.conf $< > $@
+
+.adoc.htmlbody:
+ mkwb htmlbody $< > $@
+
+.htmlbody.html:
+ mkwb html $< > $@
+
+.conf.htmlheader:
+ mkwb html -H $< > $@
+
+.conf.htmlfooter:
+ mkwb html -F $< > $@
+
+.adoc.snippets:
+ mkwb snippets $< > $@
+
+.conf.indexentry:
+ mkwb indexentry $< > $@
+
+.htmlbody.feedentry:
+ mkwb feedentry $< > $@
+
+.conf.mapentry:
+ mkwb mapentry $< > $@
+
+.conf.sortdata:
+ mkwb sortdata $< > $@
+
+.conf.categorydata:
+ mkwb categorydata $< > $@
+
+.adoc.links:
+ mkwb links $< > $@
+
+.links.caslinks:
+ grep -Ev '^(link|image):' $< | xargs -I_ sh -c '\
+ printf "%s\n" "_" | sha256sum | \
+ printf "%s\t%s\n" "`cut -d" " -f1`" "_"' > $@
+
+.flac.ogg:
+ ffmpeg $(FFMFLAGS) -i $< -ar 48000 -vn -c:a libvorbis -b:a 320k $@
+
+.adoc.ps:
+ eslaides < $< > $@
+
+.ps.pdf:
+ ps2pdf - < $< > $@
+
+
+
+## Derived file lists from auto-generated source lists in deps.mk.
+listings.adoc = $(categories.adoc) $(indexes.adoc)
+sources.adoc = $(articles.adoc) $(listings.adoc) $(pages.adoc)
+sources.htmlbody = $(sources.adoc:.adoc=.htmlbody)
+sources.html = $(sources.adoc:.adoc=.html)
+sources.snippets = $(sources.adoc:.adoc=.snippets)
+sources.snippets.gz = $(sources.adoc:.adoc=.snippets.gz)
+sources.conf = $(sources.adoc:.adoc=.conf)
+sources.links = $(sources.adoc:.adoc=.links)
+sources.caslinks = $(sources.adoc:.adoc=.caslinks)
+sources.mapentry = $(sources.adoc:.adoc=.mapentry)
+articles.indexentry = $(articles.adoc:.adoc=.indexentry)
+articles.feedentry = $(articles.adoc:.adoc=.feedentry)
+articles.sortdata = $(articles.adoc:.adoc=.sortdata)
+articles.categorydata = $(articles.adoc:.adoc=.categorydata)
+listings.htmlheader = $(listings.adoc:.adoc=.htmlheader)
+listings.htmlfooter = $(listings.adoc:.adoc=.htmlfooter)
+listings.html = $(listings.adoc:.adoc=.html)
+indexes.htmllisting = $(indexes.adoc:.adoc=.htmllisting)
+categories.htmllisting = $(categories.adoc:.adoc=.htmllisting)
+categories.txt = $(categories.adoc:.adoc=.txt)
+categories.xml = $(categories.adoc:.adoc=.xml)
+categories.xml.gz = $(categories.adoc:.adoc=.xml.gz)
+sources.media.torrent = $(sources.media:=.torrent)
+slides.ps = $(slides.adoc:.adoc=.ps)
+slides.pdf = $(slides.adoc:.adoc=.pdf)
+
+sources = \
+ $(sources.adoc) \
+ $(sources.extras) \
+ $(images.svg) \
+ src/content/favicon.ico \
+ src/content/favicon.png \
+ src/content/style.css \
+ src/content/$(PUBURL) \
+
+dynamic-contents = \
+ $(sources.html) \
+ $(slides.pdf) \
+ $(feeds.xml) \
+ $(sources.media.torrent) \
+ src/content/sitemap.xml \
+
+static-contents = \
+ $(sources.extras) \
+ $(images.svg) \
+ src/content/favicon.ico \
+ src/content/favicon.png \
+ src/content/style.css \
+ src/content/$(PUBURL) \
+ src/content/.well-known/security.txt \
+
+dynamic-contents.gz = $(dynamic-contents:=.gz)
+
+static-contents.gz = \
+ $(images.svg:=.gz) \
+ src/content/favicon.ico.gz \
+ src/content/style.css.gz \
+ src/content/$(PUBURL).gz \
+ src/content/.well-known/security.txt.gz \
+
+contents.gz = \
+ $(dynamic-contents.gz) \
+ $(static-contents.gz) \
+
+contents = \
+ $(dynamic-contents) \
+ $(static-contents) \
+
+all-filelists = \
+ $(sources.snippets) \
+ $(sources.snippets.gz) \
+ $(categories.xml) \
+ $(categories.xml.gz) \
+
+all-contents = \
+ $(contents) \
+ $(contents.gz) \
+
+captured-assets = \
+ src/content/$(PUBURL) \
+ src/content/favicon.ico \
+ src/content/favicon.png \
+
+captured-assets.sentinel = $(captured-assets:=.sentinel)
+
+derived-assets = \
+ $(dynamic-contents) \
+ $(contents.gz) \
+ $(sources.html) \
+ $(sources.htmlbody) \
+ $(sources.snippets) \
+ $(sources.snippets.gz) \
+ $(sources.conf) \
+ $(sources.links) \
+ $(sources.caslinks) \
+ $(sources.mapentry) \
+ src/dyn.conf \
+ src/base.conf \
+ src/global.conf \
+ $(articles.indexentry) \
+ $(articles.feedentry) \
+ $(articles.sortdata) \
+ $(articles.categorydata) \
+ $(listings.htmlheader) \
+ $(listings.htmlfooter) \
+ $(listings.html) \
+ $(indexes.htmllisting) \
+ $(categories.htmllisting) \
+ $(categories.txt) \
+ $(categories.xml) \
+ $(categories.xml.gz) \
+ $(slides.ps) \
+ $(slides.pdf) \
+ email.txt \
+ baseurl.txt \
+ fingerprint.txt \
+ expiry.txt \
+ expiry-epoch.txt \
+ now.txt \
+ src/content/.well-known/security.txt \
+ src/all-contents.txt \
+ src/all-filelists.txt \
+ src/all-symlinks.txt \
+ src/install.txt \
+ src/sort-expected.txt \
+ src/sort-given.txt \
+ src/sources.txt \
+ install.txt \
+ sources.txt \
+ src/content/.gitignore \
+ $(captured-assets.sentinel) \
+
+side-assets = \
+ src/collections/*/*/*/*/*/*.html.*.txt \
+ src/collections/*/*/*/*/*/*.txt.gz \
+ src/collections/*/*/index.html.*.txt \
+ src/collections/*/*/sortdata.txt \
+ src/collections/*/*/feed.*.xml \
+ src/collections/*/*/feed.*.xml.gz \
+ src/collections/*/*/*.sortdata \
+ src/pages/*/*.html.*.txt \
+ src/content/.well-known/ \
+ `cat src/all-symlinks.txt 2>/dev/null` \
+ `cat src/linkonly-dirs.txt 2>/dev/null` \
+
+
+
+## Default target -- builds all derived + captured artifacts.
+all: $(derived-assets) $(captured-assets)
+
+
+$(sources.conf): src/global.conf
+
+
+src/content/.gitignore: src/symlinks.txt
+ cd src/content/ && mkwb symlinks ../symlinks.txt > $(@F)
+
+src/dyn.conf: email.txt baseurl.txt fingerprint.txt
+ printf "export url_pre='%s'\n" "`cat baseurl.txt`" > $@
+ printf "export email='%s'\n" "`cat email.txt`" >> $@
+ printf "export publickey='%s'\n" "`cat fingerprint.txt`" >> $@
+ printf "export publickey_url='$(PUBURL)'\n" >> $@
+ printf 'export sourcecode_url="$$url_pre/git/$(NAME)"\n' >> $@
+
+src/base.conf: src/dyn.conf src/static.conf
+ cat src/dyn.conf src/static.conf > $@
+
+src/global.conf: src/base.conf
+ mkwb conf -G src/base.conf > $@
+
+$(listings.html):
+ cat $*.htmlheader $*.htmlbody $*.htmllisting $*.htmlfooter > $@
+
+$(indexes.htmllisting):
+ mkwb indexbody $*.conf > $@
+
+$(categories.htmllisting):
+ mkwb categoriesbody $*.conf > $@
+
+$(categories.txt): src/global.conf
+ mkwb categories src/global.conf $(@D) > $@
+
+$(categories.xml):
+ for f in `cat $*.txt`; do \
+ c="`printf '%s\n' "$$f" | cut -d. -f2`"; \
+ mkwb feed src/global.conf "$$f" > $(@D)/feed."$$c".xml; \
+ printf '%s\n' $(@D)/feed."$$c".xml; \
+ done > $@
+
+$(feeds.xml):
+ mkwb feed src/global.conf $(@D)/sortdata.txt > $@
+
+$(contents.gz):
+ gzip -9fk $*
+ touch $@
+
+$(sources.snippets.gz) $(categories.xml.gz):
+ if [ -s $* ]; then gzip -9fk `cat $*`; fi
+ sed 's/$$/.gz/' $* > $@
+
+src/content/$(PUBURL).gz: src/content/$(PUBURL).sentinel
+src/content/$(PUBURL).sentinel: email.txt
+ gpg --export --armour "`cat email.txt`" | ifne ifnew $*
+ touch $@
+
+src/content/favicon.ico.gz: src/content/favicon.ico.sentinel
+src/content/favicon.ico.sentinel: src/content/img/favicon.svg
+ convert src/content/img/favicon.svg -strip ico:- | ifnew $*
+ touch $@
+
+src/content/favicon.png.sentinel: src/content/img/favicon.svg
+ convert src/content/img/favicon.svg -strip png:- | ifnew $*
+ touch $@
+
+$(sources.media.torrent):
+ F="`printf '%s\n' $* | cut -d/ -f3-`" && \
+ mktorrent -xfd -n $(*F) -o $@ -w "https://$(NAME)$(BASEURL)$${F}" $*
+
+src/content/sitemap.xml.gz: src/content/sitemap.xml
+src/content/sitemap.xml: $(sources.mapentry)
+ mkwb sitemap $(sources.mapentry) > $@
+
+email.txt: meta.capim
+ cat meta.capim | awk '$$1 == ":email" && $$0=$$2' | tr -d '"' > $@
+
+baseurl.txt: meta.capim
+ cat meta.capim | awk '$$1 == ":baseurl" && $$0=$$2' | tr -d '"' > $@
+
+fingerprint.txt: src/content/$(PUBURL)
+ gpg --always-trust --no-keyring --show-key --with-colons \
+ src/content/$(PUBURL) | \
+ awk -F: '/^pub:/ { print $$5 }' > $@
+
+expiry.txt: src/content/$(PUBURL)
+ gpg --always-trust --no-keyring --show-key --with-colons \
+ src/content/$(PUBURL) | \
+ awk -F: '/^pub:/ { print $$7 }' | \
+ xargs -I% date -Is -d@% > $@
+
+expiry-epoch.txt: expiry.txt
+ date -d "`cat expiry.txt`" '+%s' > $@
+
+now.txt:
+ now > $@
+
+src/content/.well-known/security.txt.gz: src/content/.well-known/security.txt
+src/content/.well-known/security.txt: email.txt baseurl.txt expiry.txt
+ mkdir -p $(@D)
+ printf 'Contact: mailto:%s\n' "`cat email.txt`" > $@
+ printf 'Expires: %s\n' "`cat expiry.txt`" >> $@
+ printf 'Encryption: %s/$(PUBURL)\n' "`cat baseurl.txt`" >> $@
+ printf 'Preferred-Languages: en, pt, fr, eo, es, de\n' >> $@
+
+src/sources.txt:
+ printf '%s\n' $(sources) > $@
+
+src/all-contents.txt:
+ printf '%s\n' $(all-contents) > $@
+
+src/all-filelists.txt: src/all-symlinks.txt
+ printf '%s\n' $(all-filelists) src/all-symlinks.txt > $@
+
+src/all-symlinks.txt: src/content/.gitignore
+ sed 's|^|src/content|' src/content/.gitignore > $@
+
+src/install.txt: src/all-contents.txt src/all-filelists.txt $(all-filelists)
+ cat src/all-contents.txt `cat src/all-filelists.txt` > $@
+
+sources.txt: src/sources.txt
+install.txt: src/install.txt
+sources.txt install.txt:
+ sed 's|^src/content/||' src/$(@F) > $@
+
+
+
+## ---- check-unit-* targets ---------------------------------------
+
+src/sort-expected.txt:
+ dirname $(articles.adoc) | env LANG=POSIX.UTF-8 sort | uniq -c | \
+ awk '{ printf "%s\t%s\n", $$2, $$1 }' > $@
+
+src/sort-given.txt: $(sources.conf) src/sort-expected.txt
+ awk '{ \
+ "grep \"^export sort=\" " $$1 "/*.conf | wc -l" | getline cnt; \
+ printf "%s\t%s\n", $$1, cnt; \
+ }' src/sort-expected.txt > $@
+
+check-unit-sorting: src/sort-expected.txt src/sort-given.txt
+ diff -U10 src/sort-expected.txt src/sort-given.txt
+
+
+.SUFFIXES: .updatedat-check
+sources.updatedat-check = $(sources.adoc:.adoc=.updatedat-check)
+$(sources.updatedat-check):
+ . ./$*.conf && if [ -n "$$updatedat_epoch" ] && \
+ [ "$$updatedat_epoch" -le "$$date_epoch" ]; then exit 3; fi
+
+check-unit-updatedat: $(sources.updatedat-check)
+
+
+.SUFFIXES: .links-internal-check
+sources.links-internal-check = $(sources.adoc:.adoc=.links-internal-check)
+$(sources.links-internal-check): $(sources.html) $(slides.pdf)
+ grep -E '^(link|image):' $*.links | cut -d: -f2- | \
+ xargs -I% test -e $(*D)/%
+
+check-unit-links-internal: $(sources.links-internal-check)
+
+
+check-unit-links-external:
+
+
+symlink-deps = \
+ $(sources.html) \
+ $(feeds.xml) \
+ $(categories.xml) \
+ src/content/.well-known/security.txt \
+ $(sources.media.torrent) \
+
+check-unit-links-symlinks: src/all-symlinks.txt $(symlink-deps)
+ find `cat src/all-symlinks.txt` | xargs -n1 test -e
+
+
+check-unit-links: check-unit-links-internal check-unit-links-external
+check-unit-links: check-unit-links-symlinks
+
+
+MAXSIZE = 52428800 # from spec: https://www.sitemaps.org/protocol.html
+check-unit-sitemap-size: src/content/sitemap.xml
+ test "`stat --printf='%s' src/content/sitemap.xml`" -le $(MAXSIZE)
+
+check-unit-sitemap-count: src/content/sitemap.xml
+ test "`grep -cF '</url>' src/content/sitemap.xml`" -le 50000
+
+check-unit-sitemap: check-unit-sitemap-count check-unit-sitemap-size
+
+
+check-unit-expiry: expiry-epoch.txt now.txt
+ test "`cat expiry-epoch.txt`" -gt "`cat now.txt`"
+
+
+check-unit: check-unit-sorting check-unit-updatedat check-unit-links
+check-unit: check-unit-sitemap check-unit-expiry
+
+
+## ---- standard housekeeping --------------------------------------
+
+## Remove all derived artifacts produced during the build.
+clean:
+ rm -rf $(derived-assets) $(side-assets)
+
+
+## Install into $(DESTDIR)$(PREFIX).
+install: all
+ rsync --mkpath -a --files-from=install.txt src/content/ \
+ '$(DESTDIR)$(HTMLDIR)'
+ rsync --mkpath -a --files-from=sources.txt src/content/ \
+ '$(DESTDIR)$(SRCDIR)'
+
+## Remove what install placed.
+uninstall:
+ rm -rf \
+ '$(DESTDIR)$(SRCDIR)' \
+ '$(DESTDIR)$(HTMLDIR)' \
+
+
+ALWAYS:
diff --git a/meta.capim b/meta.capim
index ba9dd94..34e233e 100644
--- a/meta.capim
+++ b/meta.capim
@@ -2,4 +2,10 @@
:description "Landing page for Papo website (papo.im)."
:baseurl "https://papo.im"
:email "support@papo.im"
+ :dependencies {
+ :build #{
+ eslaides
+ mkwb
+ }
+ }
}
diff --git a/mkdeps.sh b/mkdeps.sh
index 9df3e5a..95d8d00 100755
--- a/mkdeps.sh
+++ b/mkdeps.sh
@@ -164,3 +164,10 @@ for langlink in src/collections/*; do
collectionentries "$langlink" "$colllink"
done
done
+
+## Inline the canonical mkwb rules at the end of deps.mk so that
+## the variable assignments above are visible when those rules
+## parse `all: $(derived-assets)` and its prereq list expands at
+## parse time. Self-contained -- no make-time include needed.
+echo
+mkwb rules