Mike Gerwitz

Activist for User Freedom

aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore16
-rw-r--r--.gitmodules6
-rw-r--r--Makefile201
-rw-r--r--README3
-rwxr-xr-xbootstrap77
-rwxr-xr-xbuild-aux/lsfonts22
-rwxr-xr-xbuild-aux/mkmk48
m---------docs/papers/coope0
-rw-r--r--fonts/.gitignore2
-rw-r--r--fonts/LICENSE.apache2201
-rw-r--r--fonts/LICENSE.txt93
-rw-r--r--fonts/OpenSans-Regular.woffbin22660 -> 0 bytes
-rw-r--r--fonts/README3
-rw-r--r--fonts/SHA512SUM3
-rw-r--r--images/tp/SHA256SUM1
-rw-r--r--images/tp/SHA512SUM3
-rwxr-xr-ximages/tp/gen-makefile6
-rw-r--r--images/tp/remote-list4
m---------papers/coope0
m---------papers/cptt0
-rw-r--r--src/404.htm20
-rw-r--r--src/about.htm90
-rw-r--r--src/about/githubbub.md126
-rw-r--r--src/about/inside.htm47
-rw-r--r--src/about/resume.html (renamed from docs/about/resume.html)0
-rw-r--r--src/about/resume/.gitignore (renamed from docs/about/resume/.gitignore)0
-rw-r--r--src/about/resume/style-print.css (renamed from docs/about/resume/style-print.css)0
-rw-r--r--src/about/resume/style.css (renamed from docs/about/resume/style.css)0
-rw-r--r--src/footer.tpl.htm107
-rwxr-xr-xsrc/h12title43
-rw-r--r--src/header.tpl.htm30
-rwxr-xr-xsrc/index.sh133
-rwxr-xr-xsrc/mkheader53
-rw-r--r--src/pandoc.tpl28
-rw-r--r--src/papers.rec41
-rwxr-xr-xsrc/papers.sh183
-rwxr-xr-xsrc/post2html96
-rwxr-xr-xsrc/post2meta80
-rwxr-xr-xsrc/posts.sh103
-rwxr-xr-xsrc/rss.sh115
-rw-r--r--src/talks.rec81
-rwxr-xr-xsrc/talks.sh101
-rw-r--r--style.css935
43 files changed, 2248 insertions, 853 deletions
diff --git a/.gitignore b/.gitignore
index 4d13571..02b5472 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,11 @@
*.html
-!docs/about/resume.html
+!/src/about/resume.html
+*.meta
+*.mk
+/post/list
+!/docs/about/resume.html
rss.xml
-www-root
-docs/papers/.list
+/www-root
+/papers/*.pdf
+/papers/*.dvi
-# repo2html
-.clist
-.cref-bad
-.cref-errlog
-.hashcache
diff --git a/.gitmodules b/.gitmodules
index 50c2e22..04707be 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,9 @@
[submodule "docs/papers/cptt"]
path = docs/papers/cptt
url = https://mikegerwitz.com/projects/cptt
+[submodule "papers/cptt"]
+ path = papers/cptt
+ url = https://mikegerwitz.com/projects/cptt
+[submodule "papers/coope"]
+ path = papers/coope
+ url = https://mikegerwitz.com/projects/coope
diff --git a/Makefile b/Makefile
index 9a8dad4..20a9475 100644
--- a/Makefile
+++ b/Makefile
@@ -1,107 +1,136 @@
# Builds thoughts (well, not quite like that)
#
-# Copyright (C) 2013 Mike Gerwitz
+# Copyright (C) 2013, 2018, 2019 Mike Gerwitz
#
-# This program is free software: you can redistribute it and/or modify
+# This program is free software: you can rewww-ribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
-# This program is distributed in the hope that it will be useful,
+# This program is www-ributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-# #
-
-pages := $(patsubst %.pg, %.html, \
- $(shell find docs/ -name '*.pg'))
-pages_md := $(patsubst %.md, %.html, \
- $(shell find docs/ -name '*.md'))
-articles := $(patsubst %.txt, %.html, \
- $(shell find docs/ -maxdepth 2 -name '*.txt' | grep -Fv /gh/))
-# articles in TeX with an inappropriate var name
-texticles=$(patsubst %/, %.html, $(dir $(shell find docs/ -name 'Makefile')))
-www_root := www-root/
-url_root := https://mikegerwitz.com
-repo_url := https://mikegerwitz.com/projects/thoughts
-repo_commit_url := '$(repo_url)/commit/?id=%s'
-
-# configured repo2html command
-repo2html := repo2html \
- -t 'Mike Gerwitz' \
- -d 'Free Software Hacker+Activist' \
- -c 'Mike Gerwitz' \
- -l 'This content is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.' \
- -C '/style.css' \
- -f 'tools/thoughts-fmt' \
- -F .listfilter \
- -T '$(PWD)/tpl' \
- -u '$(repo_url)' \
- -U '$(repo_commit_url)' \
- -E ''
-
-.PHONY: default clean pages articles thoughts docs
+#
+# This project is a static site generator. This Makefile was written to
+# have deep knowledge of every aspect of the site so that it can be
+# incrementally built, and so that all relevant portions will be properly
+# rebuilt any time something changes.
+#
+# Source files are automatically identified through either wildcards or
+# Makefile generation with one important exception: things in src/. The
+# reason is that src/ contains a number of things we don't want published,
+# and the distinction is too messy to codify. Of course, another option is
+# to clean that up, but I don't mind being explicit for now.
+##
+
+.DELETE_ON_ERROR:
+
+postsrc := $(wildcard post/*.md)
+pmeta := $(postsrc:.md=.meta)
+phtml := $(postsrc:.md=.html)
+pmk := $(pmeta:.meta=.mk)
+
+www-root = www-root
+
+# articles in TeX
+texticles = $(wildcard papers/*/)
+www-paper = $(patsubst papers/%/, $(www-root)/papers/%.pdf, $(texticles)) \
+ $(patsubst papers/%/, $(www-root)/papers/%.dvi, $(texticles))
+
+images = $(wildcard images/*.*) $(wildcard images/tp/*.*)
+www-images = $(patsubst images/%, $(www-root)/images/%, $(images))
+
+cssfonts := $(shell build-aux/lsfonts)
+www-fonts := $(patsubst fonts/%, $(www-root)/fonts/%, $(cssfonts))
+
+# Manually maintain both for simplicity and to ensure something does not get
+# unintentionally published.
+srcpages = src/index.html src/about.html src/papers.html src/posts.html \
+ src/talks.html src/404.html src/about/inside.html \
+ src/about/githubbub.html \
+ src/about/resume.html $(wildcard src/about/resume/*)
+www-pages = $(patsubst src/%, $(www-root)/%, $(srcpages))
+
+www-files = $(www-pages) $(www-root)/style.css $(www-root)/rss.xml $(www-paper) \
+ $(www-images) $(www-fonts)
+
+RSS_N=10
+export WWW_URL
+
+
+.PHONY: default clean webroot
default: www-root
-thoughts:
- mkdir -p "$(www_root)"
- $(repo2html) \
- -R 40 \
- -o "$(www_root)" \
- '$(url_root)' \
- > "$(www_root)/index.html"
-
-# all .txt articles will be compiled with asciidoc, then post-processed with the
-# mgify script
-%.html: %.txt
- asciidoc -fasciidoc.conf -v \
- -a stylesdir= \
- -a themedir=$(PWD)/ \
- $<
- ./tools/mgify "$@"
-
-# "pages"
-%.html: %.pg docs/papers/.list tpl/.config
- $(repo2html) -icontent -ftools/extfmt <$< >$@
-%.html: %.md tpl/.config
- $(repo2html) -icontent -ftools/mdfmt <$< >$@
-
-# TeX papers are expected to have their own makefiles as well as an abstract.tex
-%.html: %/abstract.tex
- $(MAKE) -C '$(dir $<)' pdf dvi
- url_root='$(url_root)' ./tools/texdoc '$(dir $<)' | $(repo2html) -icontent -ftools/extfmt >$@
+%.meta: %.html src/post2meta src/post2html
+ src/post2meta $< > $@
+src/talks.html: src/talks.rec
+src/papers.html: src/papers.rec
+%.html %.xml: %.sh post/list src/mkheader src/header.tpl.htm src/footer.tpl.htm $(phtml)
+ $< > $@
+%.html: %.md src/post2html src/mkheader src/h12title src/header.tpl.htm src/footer.tpl.htm src/pandoc.tpl
+ src/post2html $< > $@
+%.html: %.htm src/mkheader src/h12title src/header.tpl.htm src/footer.tpl.htm
+ src/mkheader about @__PAGE_TITLE__@ \
+ | cat - $< src/footer.tpl.htm \
+ | src/h12title @__PAGE_TITLE__@ \
+ > $@
+
+# special outputs
+src/rss.xml: src/rss.sh post/list $(phtml)
+ head -n$(RSS_N) post/list | xargs $< > $@
+
+posts: $(pmeta) $(phtml)
+post/list: $(pmeta)
+ ls post/*.meta | sort -rn > $@
+
+# Rules for generating the final webroot from the posts are themselves
+# generated. This also appends dependencies to www-posts.
+.PHONY: www-posts
+post/%.mk: post/%.meta build-aux/mkmk
+ build-aux/mkmk $(www-root) $< > $@
+
+# Note the conditional include only for webroot. This is needed for two
+# reasons:
+# 1. To avoid including them on `clean' (see GNU Make manual, which is
+# where this snippet originated from); and
+# 2. Because otherwise including the makefiles causes every pmete to be
+# built, which is unnecessary for all but `webroot'.
+#
+# The alternative (and perhaps more proper means) to #2 would be to run mkmk
+# as part of the meta target. This was originally done until a solution to
+# `clean' was needed; this handles both situations well.
+ifeq ($(MAKECMDGOALS),webroot)
+include $(pmk)
+endif
+
+webroot: www-posts $(www-files)
+$(www-root)/style.css: style.css
+ install -Dma+r $< $@
+$(www-root)/%: src/%
+ install -Dma+r $< $@
+$(www-root)/fonts/%: fonts/%
+ install -Dma+r $< $@
+$(www-root)/papers/%: papers/%
+ install -Dma+r $< $@
+$(www-root)/images/%: images/%
+ install -Dma+r $< $@
+
+
+# TeX papers are expected to have their own Makefiles as well as an abstract.tex
+papers/%.pdf: papers/%/abstract.tex
+ $(MAKE) -C $(dir $<) pdf
+ cp $(dir $<)/$*.pdf $@
+papers/%.dvi: papers/%/abstract.tex
+ $(MAKE) -C $(dir $<) dvi
+ cp $(dir $<)/$*.dvi $@
docs/papers/.list: thoughts articles
echo "$(articles) $(texticles)" | tr ' ' '\n' | tools/doclist >$@
-images: images/tp/Makefile
- $(MAKE) -C '$(dir $<)' all check
-images/tp/Makefile: images/tp/gen-makefile
- ( cd images/tp/ && ./gen-makefile ) >$@
-
-pages: $(pages) $(pages_md)
-articles: $(articles) $(texticles)
-docs: pages articles
-www-root: docs thoughts images
- mkdir -p www-root/papers
- ( cd docs/ \
- && find . -maxdepth 2 -name '*.html' -exec ../tools/doc-cp {} ../www-root/{} \; \
- && find . -maxdepth 3 \( -name '*.pdf' -o -name '*.dvi' \) -exec cp {} ../www-root/{} \; \
- )
- mkdir -p www-root/images/
- cp -v images/*.* images/tp/*.png www-root/images/
- cp -rv fonts/ www-root/
- cp -rv _raw/* www-root/
- cp -v style.css www-root/
- mkdir -p www-root/docs
- cp -rv docs/gh/ www-root/docs/
- cp -rv docs/about/resume www-root/about/
- cp -rv docs/hoxsl www-root/hoxsl
-
clean:
- rm -rf www-root/
- rm -f $(pages) $(pages_md) $(articles) $(texticles)
+ rm -rf $(www-root) $(pmeta) $(phtml) $(pmk)
diff --git a/README b/README
index e8d6356..52de14f 100644
--- a/README
+++ b/README
@@ -1,5 +1,4 @@
The miscellaneous thoughts and ramblings of a free software hacker.
-This website is processed with repo2html.
+https://mikegerwitz.com/
-http://mikegerwitz.com/
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..a41c9f8
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,77 @@
+#!/bin/bash
+# Prepares build environment
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# This will also download any necessary third-party files. Note that all
+# downloads are proxied over Tor (using `torify').
+##
+
+set -euo pipefail
+
+# Source fonts and license (SIL Open Font License 1.1)
+declare -ra fonts=(
+ https://github.com/adobe-fonts/source-sans-pro/raw/c7ea228c8cd66f65dac985bef98fda12c9cfa713/WOFF/OTF/SourceSansPro-Light.otf.woff
+ https://github.com/adobe-fonts/source-sans-pro/raw/c7ea228c8cd66f65dac985bef98fda12c9cfa713/WOFF/OTF/SourceSansPro-Regular.otf.woff
+ https://github.com/adobe-fonts/source-sans-pro/raw/c7ea228c8cd66f65dac985bef98fda12c9cfa713/LICENSE.txt
+)
+
+declare -r tpimagesdir=images/tp
+declare -r fontdir=fonts
+
+
+# Download third-party images. This not only keeps them out of the
+# repository, but explicitly states in a reproducible manner how the images
+# were manipulated (if at all).
+get-images()
+{
+ echo 'retrieving third-party images...'
+
+ ( cd "$tpimagesdir" && ./gen-makefile > Makefile )
+ make -C "$tpimagesdir" all check
+}
+
+
+# Download and verify fonts and license.
+get-fonts()
+{
+ local font dest
+
+ echo 'retrieving font files...'
+ for font in "${fonts[@]}"; do
+ dest="$fontdir/$( basename "$font" )"
+
+ test ! -f "$dest" || continue
+ torify wget "$font" -O "$dest"
+ done
+
+ # Verify that we haven't been served bad files. This should only happen
+ # in the case of network failure or a malicious host, since the above URLs
+ # reference the commit hash.
+ echo 'verifying font files...'
+ ( cd "$fontdir" && sha512sum -c SHA512SUM )
+}
+
+
+# Bootstrap.
+main()
+{
+ get-images
+ get-fonts
+}
+
+
+main "$@"
diff --git a/build-aux/lsfonts b/build-aux/lsfonts
new file mode 100755
index 0000000..652615e
--- /dev/null
+++ b/build-aux/lsfonts
@@ -0,0 +1,22 @@
+#!/bin/sh
+# List fonts used by CSS
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+##
+
+grep -A2 @font-face style.css \
+ | grep -o "fonts/[^']\+"
+
diff --git a/build-aux/mkmk b/build-aux/mkmk
new file mode 100755
index 0000000..4f6a983
--- /dev/null
+++ b/build-aux/mkmk
@@ -0,0 +1,48 @@
+#!/bin/bash
+# Generate dependency Makefile for post
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# The dependency Makefile is responsible for webroot generation. This is
+# necessary since the directory structure of the webroot varies so wildly
+# from that of the source.
+##
+
+set -euo pipefail
+
+
+# Generate Makefile. Produces webroot target and adds that target to the
+# `www-posts' phony target.
+main()
+{
+ local -r distdir=${1?Missing distdir}
+ local -r meta=${2?Missing post path}
+
+ local slug
+ slug=$( recsel -P slug "$meta" )
+
+ local -r dest="$distdir/$slug.html"
+ local -r src="${meta%%.meta}.html"
+
+ cat <<EOF
+www-posts: $dest
+$dest: $src
+ install -Dma+r $src $dest
+EOF
+}
+
+
+main "$@"
diff --git a/docs/papers/coope b/docs/papers/coope
deleted file mode 160000
-Subproject 98583d0e9f72a6e0af4117f013679fca1978f1d
diff --git a/fonts/.gitignore b/fonts/.gitignore
new file mode 100644
index 0000000..8ba498c
--- /dev/null
+++ b/fonts/.gitignore
@@ -0,0 +1,2 @@
+*.woff
+
diff --git a/fonts/LICENSE.apache2 b/fonts/LICENSE.apache2
deleted file mode 100644
index 989e2c5..0000000
--- a/fonts/LICENSE.apache2
+++ /dev/null
@@ -1,201 +0,0 @@
-Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License. \ No newline at end of file
diff --git a/fonts/LICENSE.txt b/fonts/LICENSE.txt
new file mode 100644
index 0000000..87ec82c
--- /dev/null
+++ b/fonts/LICENSE.txt
@@ -0,0 +1,93 @@
+Copyright 2010, 2012, 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/fonts/OpenSans-Regular.woff b/fonts/OpenSans-Regular.woff
deleted file mode 100644
index e231183..0000000
--- a/fonts/OpenSans-Regular.woff
+++ /dev/null
Binary files differ
diff --git a/fonts/README b/fonts/README
index 30061b6..1b1fc1e 100644
--- a/fonts/README
+++ b/fonts/README
@@ -1,2 +1 @@
-Open Sans by Steve Matteson
-Apache 2.0 License
+Run bootstrap to retrieve fonts and license
diff --git a/fonts/SHA512SUM b/fonts/SHA512SUM
new file mode 100644
index 0000000..cb047b5
--- /dev/null
+++ b/fonts/SHA512SUM
@@ -0,0 +1,3 @@
+49a33ee66a091e2662e92d71c540bbf4a5ba9d7d42d756895d896f5da330c1c3c10d5edbafa81ca333b18c5c5de5c3ac993ca5c6b8a2652620cd9dd12a316b32 SourceSansPro-Light.otf.woff
+d66af3a26a1a9713a701aceae0b3e69373f4741f4368c83585ff34586cdf55ddcfa15b67bf186c9eaaf21c91c285454f1ac7506271792be98bbb348cdcbf8718 SourceSansPro-Regular.otf.woff
+8a9c50f8246cddd6b2da4ed34dc501e254bc66cda1d1593ef4c048c6f14616e6f7c43bc6e9d5aeb91a4d693bc9d1baa4d5db90655eecfe28437ae8b741c142ee LICENSE.txt
diff --git a/images/tp/SHA256SUM b/images/tp/SHA256SUM
deleted file mode 100644
index a77793c..0000000
--- a/images/tp/SHA256SUM
+++ /dev/null
@@ -1 +0,0 @@
-3a2fb99c4cbb929ee7a5c404f7b356fa9c5133145feaf834220cad4362d651d0 eff-42.png
diff --git a/images/tp/SHA512SUM b/images/tp/SHA512SUM
new file mode 100644
index 0000000..9dbaa90
--- /dev/null
+++ b/images/tp/SHA512SUM
@@ -0,0 +1,3 @@
+3a91c74bec2dc9b65df8a0208b2f640b1971131c2791c8f3f8431219405702e600bdc476f0f792856f7c31f8b8144d125c934105287913a822d14c0aef058993 eff-42.png
+81db76e73f274194c82695eb314cae4b371f3a1cb246a18ff702b26440dbe73bb110a8695230c4d75e628f652a245e3675541144003975a650aa5edecb5f72f3 eff-privacy.png
+794b6aca4d20e60f876b38127a5d3f5975e4c99b0520dfd8a1895df00b9168f07cf650fb2d2a4d7d818a74d3a9e5a252b94ef70cf50fb17484f4272408420ba9 fsfs-icons-beige.png
diff --git a/images/tp/gen-makefile b/images/tp/gen-makefile
index 85764e2..0b99526 100755
--- a/images/tp/gen-makefile
+++ b/images/tp/gen-makefile
@@ -29,11 +29,11 @@ images := $( cut -d' ' -f1 "$remote_file" | tr '\n' ' ' )
.PHONY: all check clean
all: \$(images)
-SHA256SUM: \$(images)
- sha256sum \$(images) > \$@
+SHA512SUM: \$(images)
+ sha512sum \$(images) > \$@
check:
- sha256sum -c SHA256SUM
+ sha512sum -c SHA512SUM
clean:
\$(RM) \$(images)
diff --git a/images/tp/remote-list b/images/tp/remote-list
index 84119f5..f92aaf1 100644
--- a/images/tp/remote-list
+++ b/images/tp/remote-list
@@ -1 +1,5 @@
eff-42.png https://web.archive.org/web/20170922020250/https://www.eff.org/files/2014/01/24/eff-logo-plain-rgb.png -trim -resize 42 -gravity center -extent 42x42
+eff-privacy.png https://web.archive.org/web/20190102234255/https://www.eff.org/files/issues/icon-privacy-1_0.png -scale x250 -crop 250x250+125+0
+fsfs-icons-beige.png https://web.archive.org/web/20190105011705/http://static.fsf.org/nosvn/images/badges/fsfs_icons_beige-bg.png
+lp-2017-crop.png https://web.archive.org/web/20181208025632/https://libreplanet.org/2017/assets/img/site_logo_alternate.png -crop 75x75+29+0
+
diff --git a/papers/coope b/papers/coope
new file mode 160000
+Subproject 93fa274206c70606fca0b42d9329e3f8565816f
diff --git a/papers/cptt b/papers/cptt
new file mode 160000
+Subproject 41a35f3c37fd41772ff7ae8aca62d77c4cafcf6
diff --git a/src/404.htm b/src/404.htm
new file mode 100644
index 0000000..4a1231e
--- /dev/null
+++ b/src/404.htm
@@ -0,0 +1,20 @@
+<article>
+ <h1>Page Not Found</h1>
+
+ <p>
+ Sorry&nbsp;the page you requested cannot be found; it may have been removed
+ or you may have stumbled across a broken link. If you believe that you
+ have received this message in error, please contact Mike directly. If
+ you have arrived at this page from an external link, please contact the
+ author of that website instead.
+ </p>
+
+ <p>
+ [This is where one would insert the obligatory &ldquo;we apologize for the
+ inconvenience&rdquo;...but this is a personal site, not a business, so I'm not all
+ that sympathetic. If it's a bug, it'll be fixed. If you think that the page
+ you're looking for should exist (and that it did in the past), consider looking
+ through this site's repository (available on the Projects page) and seeing what
+ might have happened to it. Good day to you, kind sir/madam/otherwise.]
+ </p>
+</article>
diff --git a/src/about.htm b/src/about.htm
new file mode 100644
index 0000000..c8622ef
--- /dev/null
+++ b/src/about.htm
@@ -0,0 +1,90 @@
+<aside class="sm">
+ <img src="/images/me-libreplanet-2016.png"
+ alt="Photo of Mike Gerwitz holding a microphone in front of a blackboard"
+ title="Mike Gerwitz giving LibrePlanet 2016 Talk 'Restore Online Freedom!'"
+ class="inline-img avatar" />
+
+ <p>
+ GPG Fingerprint: <tt>D6E9 B930 028A 6C38 F43B 2388 FEF6 3574 5E6F 6D05</tt>
+ <a href="https://emailselfdefense.fsf.org/">[?]</a>
+ </p>
+ <ul class="links">
+ <li><a href="about/resume">View my résumé/CV.</a></li>
+ </ul>
+</aside>
+
+<article class="abstract">
+ <h1>About</h1>
+
+ <p>
+ I am a <a href="http://www.gnu.org/philosophy/">free (as in
+ freedom) software</a> <a href="https://stallman.org/articles/on-hacking.html">hacker</a>
+ and user freedom activist with a focus on user privacy and security.
+ I am a professional software developer dealing primarily with web development;
+ compiler construction; and software architecture, and have been
+ programming for about twenty years.
+ My other personal interests include mathematics, cryptography,
+ philosophy and ethics, pedagogy, writing, law, and various other fields.
+ I also closely follow the work of
+ the <a href="http://www.gnu.org/philosophy/">Free Software
+ Foundation</a>, <a href="http://eff.org/">Electronic Frontier
+ Foundation</a>, and other entities devoted to free information and free
+ society.
+ </p>
+ <p>
+ I am the author of <a href="https://gnu.org/software/easejs">GNU
+ ease.js</a>;
+ a member of the <a href="https://www.gnu.org/help/evaluation.html">GNU evaluation</a>
+ team;
+ hold an administrative role within GNU;
+ and volunteer for various other aspects of
+ the <a href="https://gnu.org/">GNU Project</a> and
+ the <a href="https://fsf.org/">Free Software Foundation</a>.
+ </p>
+ <p>
+ I am a <a href="https://stallman.org/articles/on-hacking.html">hacker</a>,
+ not a <a href="https://stallman.org/articles/on-hacking.html">cracker</a>&mdash;the
+ latter breaks the security of systems, while the former expresses playful
+ creativity in their work.
+ </p>
+ <p>
+ Outside of my field,
+ I enjoy time with my family&mdash;including my wife and two
+ sons&mdash;who
+ keep me very busy and help to keep me sane.
+ I also have a fascination with a wide range of sciences that I wish I had
+ the time to devote to researching.
+ </p>
+ <p>
+ Much of this site is devoted to my thoughts and ramblings on various
+ matters and so will contain material that is subject to strong bias;
+ you are encouraged to construct your own opinions.
+ Formal papers contain no such influence without rationale and references.
+ </p>
+ <p>
+ I may be contacted at mtg at gnu dot org.
+ I do not make use of &ldquo;social media&rdquo; websites,
+ though I may (or may not) respond to queries on websites that I am a
+ member of,
+ and I do host my <a href="https://social.mikegerwitz.com/">own GNU
+ Social instance</a>.
+ </p>
+ <p>
+ (Note: This website itself is free/libre&mdash;the source code is
+ available via the commit hash links in the footer of various pages and
+ the content is licensed for free distribution and, in most cases,
+ modification.)
+ </p>
+ <p>
+ I changed GPG keys in October&nbsp;2016;
+ see my <a href="/about/key-transition.txt">key transition statement</a>,
+ signed with both my <a href="/about/key-transition.txt.new.asc">new</a>
+ and <a href="/about/key-transition.txt.old.asc">old</a> keys.
+ </p>
+ <p>
+ <span class="attribution"><a href="https://media.libreplanet.org/u/libreplanet/m/session-03-c-ms-png-libreplanet-2016-sessions-ec00/">LibrePlanet
+ 2016 Photo</a> Copyright&nbsp;©&nbsp;2016 Kori&nbsp;Feener,
+ <a href="https://creativecommons.org/licenses/by/4.0/">CC&nbsp;BY&nbsp;4.0</a>;
+ used with permission.</span>
+ </p>
+</article>
diff --git a/src/about/githubbub.md b/src/about/githubbub.md
new file mode 100644
index 0000000..9893929
--- /dev/null
+++ b/src/about/githubbub.md
@@ -0,0 +1,126 @@
+# GitHubbub! GitHub Does Not Value Software Freedom.
+
+<div class="inline-img octoflop">
+ ![GitHub](/images/octoright-large.png "GitHub logo rotated 270° to resemble a Copyright symbol")\
+</div>
+
+If you hit this page expecting to have been taken to my GitHub profile,
+ then this is probably not what you were looking for;
+ but let me tell you why you're here.
+
+Before providing a link to something hosted on a service,
+ it is important to consider whether the service or website is antithetical
+ to the message you are trying to convey to your readers/visitors,
+ and whether it deserves clarification;
+ there's a little bit of both here.
+
+If you're looking for a host friendly toward free software,
+ take a look at the [GNU ethical repository criteria][gnu-repo],
+ which sets standards for acceptable hosts to parts of the
+ [GNU operating system][gnu].
+
+
+## Non-Free JavaScript
+[Free software][freesw] guarantees your freedom to study,
+ modify,
+ and share the software that you use.
+We value these freedoms on the desktop,
+ so why should we compromise when websites serve proprietary JavaScript
+ [just because it creates the illusion of remote execution][whyfreejs]?
+When you visit a website that serves JavaScript to the client,
+ your web browser is automatically [downloading and executing][jstrap]
+ (often without your permission) ephemeral, unsigned, untrusted software.
+If that JavaScript is not [freely licensed][librejs],
+ then the software running in your web browser is proprietary.
+
+**When you visit `github.com`,
+ you download over 200kB of obfuscated code,
+ much of which is proprietary.**
+This code provides many website features that are fairly essential,
+ and *do not work with JavaScript disabled*:
+
+- Change repository names or descriptions;
+- Delete repositories;
+- Add an SSH key to your account;
+- Fork repositories;
+- Create pull requests;
+- Enable and disable project features;
+- Use the wiki and issue trackers;
+- View graphs of statistics;
+- And others.
+
+That is---GitHub forces you to run proprietary software in order to use much
+ of their website.
+This is a bit startling for a host that owes its very existence to the
+ success and development of free software.
+
+## Desire To Remain Non-Free
+I contacted GitHub back in April 2014 pointing out these concerns and
+ asking if they would be able to either liberate their JavaScript or make
+ GitHub's essential functionality work without JavaScript enabled.
+The first response I received was from one of their "JavaScript Developers":
+
+> Hi Mike,
+>
+> Thanks for getting in touch with us here. Some of our internal projects are
+> specific to running GitHub, and as such will probably remain closed. We do
+> make an effort to open source projects that we create that we think would be
+> beneficial to the community, some of which is JavaScript.
+>
+> You can see a list of some of the open source projects that power GitHub
+> here:
+>
+> https://github.com/showcases/projects-that-power-github
+
+This response is unfortunately misguided---yes,
+ it is good that GitHub produces free software,
+ but it is a false assumption that their proprietary code would serve no
+ benefit to the community:
+ the very existence of their proprietary software [gives them unjust
+ control over their users][unjust];
+ relinquishing that control is of benefit to the community.
+
+I replied to the above message to clarify my point.
+After receiving no response,
+ I forwarded the e-mail to GitHub's original founders:
+ [Tom Preston-Werner][tom],
+ [Chris Wanstrath][chris],
+ and [PJ Hyett][pj].
+The response I received from Chris was blunt and discouraging:
+
+> Hey Mike,
+>
+> We have no plans to release github.com's JavaScript as free software at
+> this time, nor do we have plans to remove the site's dependence on
+> JavaScript. Thanks for the interest.
+
+The original correspondence is provided here:
+
+1. [Original request][gh-request] to `support@github.com`, Tom, Chris, and
+ PJ.
+2. [Reply to my original request][gh-request-reply] from one of the developers.
+3. [My reply to the developer][gh-request2] providing more information and
+ asking for a commitment.
+4. [Forward of my reply][gh-request3] to Tom, Chris, and PJ, after having
+ received no response from the developer.
+5. [Response from Chris Wanstrath][gh-request3-reply] stating that GitHub
+ has "no plans" to liberate its JavaScript or "remove the site's
+ dependence on JavaScript".
+
+
+[gnu-repo]: https://www.gnu.org/software/repo-criteria.html
+[gnu]: https://www.gnu.org/gnu/gnu.html
+[freesw]: https://www.gnu.org/philosophy/free-sw.html
+[whyfreejs]: https://www.gnu.org/software/easejs/whyfreejs.html
+[jstrap]: https://www.gnu.org/philosophy/javascript-trap.html
+[librejs]: https://www.gnu.org/software/librejs/free-your-javascript.html
+[unjust]: https://www.gnu.org/philosophy/free-software-even-more-important.html
+[tom]: https://github.com/mojombo
+[chris]: https://github.com/defunkt
+[pj]: https://github.com/pjhyett
+
+[gh-request]: /docs/gh/email-request.txt
+[gh-request-reply]: /docs/gh/email-request-reply.txt
+[gh-request2]: /docs/gh/email-request2.txt
+[gh-request3]: /docs/gh/email-request3.txt
+[gh-request3-reply]: /docs/gh/email-request3-reply.txt
diff --git a/src/about/inside.htm b/src/about/inside.htm
new file mode 100644
index 0000000..6a815da
--- /dev/null
+++ b/src/about/inside.htm
@@ -0,0 +1,47 @@
+<article>
+ <h1>GNU/Linux Inside</h1>
+
+ <img src="/images/heckert-gnu.png" alt="A Big GNU Head"
+ title="GNU" />
+
+ <p>
+ This website and the server on which it is hosted is run entirely
+ by <a href="https://www.gnu.org/philosophy/">free software</a>.
+ </p>
+ <p>
+ Do you use GNU/Linux or other free software on your website? Flaunt it!
+ Feel free to place the image below on your own website, blog, or
+ anywhere else you see fit to let others know that you support GNU and
+ free software.
+ </p>
+ <p>
+ This image also helps to bring awareness to
+ the <a href="https://www.gnu.org/">GNU operating system</a> as well as
+ <a href="https://www.gnu.org/philosophy/">GNU’s philosophy</a>. The
+ majority of users today consider the operating system to be called
+ &ldquo;Linux&rdquo;, which is false—this is the name of the kernel;
+ <a href="http://www.gnu.org/gnu/linux-and-gnu.html">GNU is the operating
+ system</a>.
+ </p>
+ <p>
+ <em>The page fold is transparent</em>; it will therefore work well with
+ any background color. Please note that this is a PNG with
+ alphatransparency—older browsers that users shouldn’t be using anymore
+ (such as IE 6) will not render it properly unless you take the necessary
+ precautions.
+ </p>
+ <p>
+ <img src="/images/gnu-inside.png" alt="GNU/Linux Inside Page Fold"
+ title="GNU/Linux Inside!">
+ </p>
+ <p>
+ Feel free
+ to <a href="https://www.gnu.org/graphics/gnu-inside.html">download the
+ source file (GIMP)</a>, released under
+ the <a href="https://creativecommons.org/licenses/by-sa/2.0/">Creative
+ Commons Attribution-ShareAlike 2.0 Unported License</a>. It
+ incorporates <a href="https://www.gnu.org/graphics/heckert_gnu.html">``A
+ Bold GNU Head’’</a> by Aurelio A. Heckert, which appears at the top of
+ this page.
+ </p>
+</article>
diff --git a/docs/about/resume.html b/src/about/resume.html
index 1da2d19..1da2d19 100644
--- a/docs/about/resume.html
+++ b/src/about/resume.html
diff --git a/docs/about/resume/.gitignore b/src/about/resume/.gitignore
index a97fa56..a97fa56 100644
--- a/docs/about/resume/.gitignore
+++ b/src/about/resume/.gitignore
diff --git a/docs/about/resume/style-print.css b/src/about/resume/style-print.css
index 96867ed..96867ed 100644
--- a/docs/about/resume/style-print.css
+++ b/src/about/resume/style-print.css
diff --git a/docs/about/resume/style.css b/src/about/resume/style.css
index b03b078..b03b078 100644
--- a/docs/about/resume/style.css
+++ b/src/about/resume/style.css
diff --git a/src/footer.tpl.htm b/src/footer.tpl.htm
new file mode 100644
index 0000000..ae3e779
--- /dev/null
+++ b/src/footer.tpl.htm
@@ -0,0 +1,107 @@
+ </main>
+
+ <footer>
+ <div>
+ <a href="/about/inside" class="page-flip">
+ <img src="/images/gnu-inside.png" alt="GNU/Linux Inside!" />
+ </a>
+ </div>
+ <nav id="selflinks" class="affiliation-list" aria-label="Affiliations">
+ <ul>
+ <li>
+ <a href="https://gitlab.com/u/mikegerwitz">
+ <img src="/images/gitlab.svg"
+ alt="mikegerwitz on GitLab"
+ title="mikegerwitz on GitLab"
+ width="42" height="42" border="0" />
+ </a>
+ </li>
+
+ <li>
+ <a href="/about/githubbub">
+ <img src="/images/octoright-42.png"
+ alt="Don't see me on GitHub"
+ title="Don't see me on GitHub"
+ width="42" height="42" border="0" />
+ </a>
+ </li>
+
+ <li>
+ <a href="https://savannah.gnu.org/users/mikegerwitz">
+ <img src="/images/meditate-42.png"
+ alt="See me on Savannah"
+ title="See me on Savannah"
+ width="42" height="42" border="0" />
+ </a>
+ </li>
+
+ <li>
+ <a href="https://news.ycombinator.com/user?id=mikegerwitz"
+ title="mikegerwitz on Hacker News"
+ class="hn-icon">HN</a>
+ </li>
+
+ <li>
+ <a href="https://www.fsf.org/register_form?referrer=5804">
+ <img src="/images/fsf-42.png"
+ alt="FSF Member #5804"
+ title="FSF Member #5804"
+ width="42" height="42" border="0" />
+ </a>
+ </li>
+
+ <li>
+ <a href="https://www.eff.org/">
+ <img src="/images/eff-42.png"
+ alt="EFF Member"
+ title="EFF Member"
+ width="42" height="42" border="0" />
+ </a>
+ </li>
+ </ul>
+ </nav>
+
+ <section class="site-nav">
+ <nav aria-labelledby="nav-general">
+ <h2 id="nav-general">General</h2>
+ <ul>
+ <li><a href="#">About</a></li>
+ <li><a href="#">Résumé</a></li>
+ <li><a href="#">GNU Social</a></li>
+ <li><a href="#">GNU/Linux Inside</a></li>
+ </ul>
+ </nav>
+
+ <nav aria-labelledby="nav-works">
+ <h2 id="nav-works">Works</h2>
+ <ul>
+ <li><a href="#">Posts</a></li>
+ <li><a href="#">Talks</a></li>
+ <li><a href="#">Projects</a></li>
+ <li><a href="#">Papers</a></li>
+ <li><a href="#">Source Code To This Site</a></li>
+ </ul>
+ </nav>
+
+ <nav aria-labelledby="nav-resources">
+ <h2 id="nav-works">Resources</h2>
+ <ul>
+ <li><a href="#">Free/Libre Software</a></li>
+ <li><a href="#">The GNU Project</a></li>
+ <li><a href="https://www.gnu.org/licenses/license-list.en.html">Free Software Licenses</a></li>
+ <li><a href="https://stallman.org/articles/on-hacking.html">Richard
+ Stallman On Hacking</a></li>
+ <li><a href="https://www.gnu.org/philosophy/proprietary.html">Proprietary
+ Software Is Often Malware</a></li>
+ </ul>
+ </nav>
+ </section>
+
+ <p id="copyright">
+ Copyright &copy; 2018 Mike Gerwitz.
+ Licensed under the Creative Commons Attribution-ShareAlike&nbsp;4.0
+ International License.
+ </p>
+ </footer>
+ </body>
+</html>
diff --git a/src/h12title b/src/h12title
new file mode 100755
index 0000000..c638b96
--- /dev/null
+++ b/src/h12title
@@ -0,0 +1,43 @@
+#!/bin/bash
+# Copies first body h1 text into title
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# This assumes that an <article> tag exists and assumes that is the main
+# content from which the title ought to be derived.
+##
+
+set -euo pipefail
+
+
+main()
+{
+ local -r placeholder=${1?Missing placeholder}
+
+ local body;
+ body=$( cat )
+
+ local title
+ title=$(
+ <<<"$body" grep -A1 '<article' \
+ | grep '<h1' \
+ | grep -oP '(?<=>)[^<]+' \
+ )
+
+ sed "s#$placeholder#${title/&/\\&}#" <<< "$body"
+}
+
+main "$@"
diff --git a/src/header.tpl.htm b/src/header.tpl.htm
new file mode 100644
index 0000000..f2aa0e7
--- /dev/null
+++ b/src/header.tpl.htm
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="alternate" title="RSS Feed"
+ href="rss.xml" type="application/rss+xml" />
+ <link rel="stylesheet" type="text/css" href="/style.css" />
+ <title>@PAGE_TITLE@Mike Gerwitz</title>
+ <meta name="viewport" content="initial-scale=1.0" />
+ </head>
+ <body class="@PAGE_TYPE@">
+ <header>
+ <hgroup id="author">
+ <h1 class="title"><a href="/">Mike Gerwitz</a></h1>
+ <h2 class="desc">Free Software Hacker+Activist</h2>
+ </hgroup>
+
+ <nav class="menu" aria-label="Main Navigation">
+ <ul>
+ <li><a href="/about">About</a></li>
+ <li><a href="/posts">Posts</a></li>
+ <li><a href="/talks">Talks</a></li>
+ <li><a href="/projects">Projects</a></li>
+ <li><a href="/papers">Papers</a></li>
+ <li><a href="//social.mikegerwitz.com/" title="My GNU Social Instance">Social</a></li>
+ </ul>
+ </nav>
+ </header>
+
+ <main>
diff --git a/src/index.sh b/src/index.sh
new file mode 100755
index 0000000..d899fcb
--- /dev/null
+++ b/src/index.sh
@@ -0,0 +1,133 @@
+#!/bin/bash
+# Generate index HTML page
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# The index page consists of post abstracts, some static text, and the
+# static header and footer. All post metadata files must have been built,
+# along with `post/list'.
+#
+# This script includes the static body (see `main').
+##
+
+set -euo pipefail
+
+
+# Get the file name of the Nth most recent post. This relies on the
+# existence of `post/list'.
+pnfile()
+{
+ local -ri n=${1?Missing relative post number}
+
+ sed "${n}q;d" post/list
+}
+
+
+# Read field FIELD from post metadata recfile FILE.
+pmeta()
+{
+ local -r file=${1?Missing file name}
+ local -r field=${2?Missing field name}
+
+ recsel -P "$field" "$file"
+}
+
+
+# Process each numeric argument using `abstract'. Each argument must be a
+# relative post number (see `pnfile').
+abstracts()
+{
+ while [ $# -gt 0 ]; do
+ abstract "$1"
+ shift
+ done
+}
+
+
+# Generate HTML for relative post number N (see `pnfile').
+abstract()
+{
+ local -ri n=${1?Missing relative post number}
+
+ local file title date slug body
+ file=$( pnfile "$n" )
+ title=$( pmeta "$file" subject )
+ date=$( pmeta "$file" date )
+ slug=$( pmeta "$file" slug )
+ body=$( pmeta "$file" abstract )
+
+ cat <<EOF
+<article class="abstract">
+ <h2 class="title"><a href="/$slug">$title</a></h2>
+ $body
+ <p class="date">Posted on $date.
+ <a href="/$slug">Read more &raquo;</a>
+ </p>
+</article>
+EOF
+}
+
+
+# Generate index HTML page.
+# TODO: Factor out static sections.
+main()
+{
+ src/mkheader index
+
+ cat <<EOF
+<aside>
+ <ul class="links">
+ <li><a class="box free-sw" href="#">What is Free/Libre Software?</a></li>
+ <li><a class="box eff-privacy" href="#">EFF on Privacy</a></li>
+ </ul>
+</aside>
+
+<section aria-labelledby="latest-posts">
+ <h1 id="latest-posts">Latest Posts</h1>
+
+ $( abstracts {1..2} )
+</section>
+
+<section class="highlight">
+ <h1 class="title">The Surreptitious Assault on Privacy, Security,
+ and Freedom</h1>
+
+ <aside>
+ Each of these essential rights are being surreptitiously
+ assaulted; only the most technical among us even know what to look
+ for, let alone how to defend ourselves. Governments, corporations,
+ and groups of ill-minded individuals are spying and preying upon
+ both users and bystanders with unprecedented frequency and
+ breadth.
+ </aside>
+
+ <a href="#" class="lp-watch">Watch LibrePlanet&nbsp;2017 Talk</a>
+</section>
+
+<section class="compact sm">
+ <h1 id="older-posts">Older Posts</h1>
+
+ $( abstracts {3..8} )
+
+ <a class="view-all" href="/posts">View all posts</a>
+</section>
+EOF
+
+ cat src/footer.tpl.htm
+}
+
+
+main "$@"
diff --git a/src/mkheader b/src/mkheader
new file mode 100755
index 0000000..292fe4f
--- /dev/null
+++ b/src/mkheader
@@ -0,0 +1,53 @@
+#!/bin/bash
+# Generate HTML header
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# The header is mostly static but contains a dynamic page type and title.
+##
+
+set -euo pipefail
+
+declare -ri EX_USAGE=64
+
+
+# Generate header by populating @PAGE_{TITLE,TYPE}@. If no title is given,
+# then the title will be completely omitted. If provided, it will have an
+# em dash delimiter appended, with whitespace on both sides for visual
+# clarity (contrary to my usual typographical conventions).
+main()
+{
+ local -r type=${1?Missing type}
+ local -r title_orig=${2:-}
+
+ local -r title=${title_orig/&/\\&amp;}
+
+ [[ $type =~ ^[a-z]+$ ]] || {
+ echo 'error: type must be an all-lowercase word'
+ exit $EX_USAGE
+ }
+
+ [[ ! $title =~ \# ]] || {
+ echo "error: title must not contain \`#'"
+ exit $EX_USAGE
+ }
+
+ sed "s#@PAGE_TITLE@#$title${title:+ \\&mdash; }#g
+ s#@PAGE_TYPE@#$type#g" \
+ src/header.tpl.htm
+}
+
+main "$@"
diff --git a/src/pandoc.tpl b/src/pandoc.tpl
new file mode 100644
index 0000000..c8deb96
--- /dev/null
+++ b/src/pandoc.tpl
@@ -0,0 +1,28 @@
+$for(include-before)$
+$include-before$
+
+$endfor$
+$if(toc)$
+$toc$
+
+$endif$
+
+<article>
+$body$
+
+$if(tags)$
+<section class="tags" aria-label="Tags">
+ <h2>Tags</h2>
+ <ul class="tags">
+ $for(tags)$
+ <li>$tags$</li>
+ $endfor$
+ </ul>
+</section>
+$endif$
+</article>
+
+$for(include-after)$
+
+$include-after$
+$endfor$
diff --git a/src/papers.rec b/src/papers.rec
new file mode 100644
index 0000000..966c6ec
--- /dev/null
+++ b/src/papers.rec
@@ -0,0 +1,41 @@
+id: git-horror-story
+type: post
+ref: 2012-05-22-git-horror-story
+
+id: coope
+type: latex
+ref: papers/coope
+pubdate: 2012-05-06
+
+id: cptt
+type: latex
+ref: papers/cptt
+pubdate: 2013-05-13
+
+id: national-uproar
+type: post
+ref: 2013-06-10-national-uproar
+
+id: gnu-kwindows
+type: post
+ref: 2016-04-06-gnu-kwindows
+
+id: gitlab-gitorious-freesw
+type: post
+ref: 2015-05-20-gitlab-gitorious-freesw
+
+id: copyleft-vs-community
+type: post
+ref: 2013-08-13-copyleft-vs-community
+
+id: re-fsf-waste-away
+type: post
+ref: 2013-01-26-re-fsf-waste-high-priority
+
+id: vlc-lgpl
+type: post
+ref: 2012-11-17-vlc-lgpl
+
+id: re-skype-let-spy
+type: post
+ref: 2013-01-30-re-skype-let-spy
diff --git a/src/papers.sh b/src/papers.sh
new file mode 100755
index 0000000..1137b29
--- /dev/null
+++ b/src/papers.sh
@@ -0,0 +1,183 @@
+#!/bin/bash
+# Generate papers HTML page
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Papers are (at least at present) written in LaTeX, whereas articles are
+# simply posts. Both are specified in $PAPERFILE. This page generates
+# abstracts for both formats, along with links to each of their output
+# formats (one or more of PDF, DVI, HTML).
+##
+
+set -euo pipefail
+
+# Refile containing paper references and metadata.
+declare -r PAPERFILE=${PAPERFILE:-src/papers.rec}
+
+
+# List ids of all papers in $PAPERFILE.
+paper-list()
+{
+ recsel -CP id "$PAPERFILE"
+}
+
+
+# Retrieve field FIELD from paper ID in $PAPERFILE.
+paper-field()
+{
+ local -r id=${1?Missing paper id}
+ local -r field=${2?Missing paper field}
+
+ recsel -P "$field" -e "id = '$id'" "$PAPERFILE"
+}
+
+
+# Read field FIELD from post metadata recfile FILE.
+post-field()
+{
+ local -r ref=${1?Missing post name}
+ local -r field=${2?Missing field name}
+
+ recsel -P "$field" "post/$ref.meta"
+}
+
+
+# Generate abstract for article or paper ID. Delegates to one of
+# {post,latex}-abstract based on its type.
+abstract()
+{
+ local -r id=${1?Missing paper id}
+
+ local type ref
+ type=$( paper-field "$id" type )
+ ref=$( paper-field "$id" ref )
+
+ case "$type" in
+ post|latex)
+ "$type-abstract" "$id" "$ref";;
+ *)
+ echo "Unknown paper type for id \`$id" >&2
+ return 1
+ esac
+}
+
+
+
+# Generate abstract for post REF.
+post-abstract()
+{
+ local -r ref=${2?Missing post ref}
+
+ local id title date abstract slug
+ id=$( post-field "$ref" id )
+ title=$( post-field "$ref" subject )
+ date=$( post-field "$ref" date )
+ abstract=$( post-field "$ref" abstract )
+ slug=$( post-field "$ref" slug )
+
+ cat <<EOF
+<article class="abstract paper">
+ <h2 class="title" id="$id"><a href="/$slug">$title</a></h2>
+
+ <ul class="links">
+ <li class="title">Formats:</li>
+ <li><a href="/$slug">View HTML</a></li>
+ </ul>
+
+ $abstract
+
+ <p class="date">Posted on $date.</p>
+</article>
+EOF
+}
+
+
+# Extract title from LaTeX document. Note that this performs no actual
+# processing on that title, so this will need to be e.g. run through Pandoc
+# in the future if titles contain something that should be parsed (like
+# dashes).
+latex-title()
+{
+ head -n1 | sed '1s/^% //;1a\\'
+}
+
+
+# Produce text of LaTeX abstract (from its abstract.tex).
+#
+# Two minor transformations are made: Footnotes are removed by exploiting
+# Pandoc's behavior of ignoring unknown/unsupported commands, since that
+# doesn't look very good in the abstract output. Emdashes have whitespace
+# on either side removed to translate to my modern convention (this can be
+# removed when old papers are updated).
+latex-abstract-text()
+{
+ sed 's/\\footnote/\\void/;
+ s/ \+--- \+/---/g' \
+ | pandoc -flatex -thtml
+}
+
+
+# Generate abstract for LaTeX document (from abstract.tex) ID located at
+# path REF. REF is expected to contain `abstract.tex' and `REF.tex', along
+# with the built `REF.pdf' and `REF.dvi'.
+latex-abstract()
+{
+ local -r id=${1?Missing paper id}
+ local -r ref=${2?Missing paper ref}
+
+ local -r abstract_tex="$ref/abstract.tex"
+ local -r main="$ref/${ref##*/}.tex"
+ local -r sans=${main%/*.tex}
+
+ local title abstract pubdate
+ title=$( latex-title < "$main" )
+ abstract=$( latex-abstract-text < "$abstract_tex" )
+ pubdate=$( paper-field "$id" pubdate )
+
+ cat <<EOF
+<article class="abstract paper">
+ <h2 class="title" id="$id"><a href="/$sans.pdf">$title</a></h2>
+
+ <ul class="links">
+ <li class="title">Formats:</li>
+ <li><a href="/$sans.pdf">View PDF</a></li>
+ <li><a href="/$sans.dvi">View DVI</a></li>
+ </ul>
+
+ $abstract
+
+ <p class="date">Published on $pubdate.</p>
+</article>
+EOF
+}
+
+
+# Generate papers page.
+main()
+{
+ src/mkheader papers Papers
+
+ local papers
+ papers=$( recsel -P id src/papers.rec )
+
+ echo '<h1>Papers / Articles</h1>'
+ paper-list | while read id; do abstract "$id"; done
+
+ cat src/footer.tpl.htm
+}
+
+
+main "$@"
diff --git a/src/post2html b/src/post2html
new file mode 100755
index 0000000..1785541
--- /dev/null
+++ b/src/post2html
@@ -0,0 +1,96 @@
+#!/bin/bash
+# Generate HTML from post Markdown source
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# This script accepts the file name rather than data on stdin because the
+# filename encodes the post date.
+#
+# Note that the `pagetitle' is set to "ignoreme"---it is not used, but is
+# needed to suppress the warning pandoc produces without suppressing all
+# warnings.
+#
+# Pandoc is used to generate the HTML and includes a (mostly) static header
+# and footer. Note that this duplicates the date logic in `post2meta',
+# because that must be run on this output, but the post must also contain
+# the date, and we want to do all HTML processing now.
+##
+
+set -euo pipefail
+
+# Pandoc output format and extensions.
+declare -ra ext=(
+ markdown
+ smart
+ footnotes
+ gfm_auto_identifiers
+ fancy_lists
+ startnum
+ tex_math_dollars
+)
+
+
+# Convert extensions to `+'-delimited string.
+pexts()
+{
+ local IFS=+
+ echo "${ext[*]}"
+}
+
+
+# Wrap h1 in an hgroup along with the post date.
+#
+# Sometimes this script is used on things that aren't posts (e.g. normal
+# pages), in which case a date will be unavailable and the output will be
+# unchanged.
+hgroup-wrap()
+{
+ local -r date=${1?Missing date}
+
+ # Abort if this is not a date prefix
+ [[ $date =~ [0-9]{4}-[0-9]{2}-[0-9]{2} ]] || {
+ cat
+ return
+ }
+
+ sed '/^<h1/{
+ i<hgroup>
+ a<h2 class="date">'"$date"'</h2></hgroup>
+ }'
+}
+
+
+# Generate HTML from post. Note that `pagetitle' is set just to suppress
+# Pandoc warnings about it missing; it is unused.
+main()
+{
+ local -r file=${1?Missing file name}
+ local -r base=$( basename "$file" .md )
+ local -r date=${base:0:10}
+
+ pandoc -f"$( pexts )" -thtml5 \
+ --standalone --template src/pandoc.tpl \
+ --metadata pagetitle:ignoreme \
+ --base-header-level=1 \
+ -B <( src/mkheader post @__PAGE_TITLE__@ ) \
+ -A src/footer.tpl.htm \
+ < "$file" \
+ | src/h12title @__PAGE_TITLE__@ \
+ | hgroup-wrap "$date"
+}
+
+
+main "$@"
diff --git a/src/post2meta b/src/post2meta
new file mode 100755
index 0000000..c50c97e
--- /dev/null
+++ b/src/post2meta
@@ -0,0 +1,80 @@
+#!/usr/bin/gawk -f
+# Cache post data in metadata recutils file
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Generates database of metadata for a given post in recutils format for use
+# by other scripts. The post must have already been converted to HTML using
+# `post2html' or some equivalent means.
+#
+# This script is also responsible for determining what constitutes the
+# abstract, which we consider to be everything after the subject line but
+# before the end-of-abstract marker "<!-- more -->". If no such marker
+# exists then the script exits in error.
+##
+
+# Output author and post date derived from the file name.
+BEGINFILE {
+ match( FILENAME, /[^/]+$/, name )
+
+ # TODO: configurable
+ print "author: Mike Gerwitz <mtg@gnu.org>"
+
+ printf "date: %s\n",
+ gensub( /^(.{10}).*$/, "\\1", "", name[0] )
+}
+
+# Wait until after <main>; everything before it is the HTML header.
+/^ *<main>/ { main=1 }
+!main { next }
+
+
+# The first header represents the subject/title and also contains the
+# unique id for this post (as generated by `post2html').
+main && /^<h1 / {
+ # Strip header tags from subject.
+ print "subject: " gensub( /<\/?h[^>]+>/, "", "g" )
+
+ # Grab the generated id from the header and use it to
+ # generate a complete slug.
+ printf "slug: %s/%s\n", \
+ gensub( /^([0-9]+)-([0-9]+).*$/, "\\1/\\2", "", name[0] ), \
+ gensub( /^<h[^>]+ id="([^"]+)".*$/, "\\1", "" )
+
+ # Skip the date line immediately following the header and grab the first
+ # line of the abstract.
+ getline
+ getline
+
+ printf "abstract: %s\n", $0
+ a = 1
+ next
+}
+
+# The end-of-abstract marker is "<!-- more -->". Until we reach that point,
+# output each line of the abstract prefixed by a `+', which is the recutils
+# line continuation marker.
+/^<!-- more -->/ { exit }
+a { printf "+ %s\n", $0 }
+
+# If we get to this point, that means that there is no end-of-abstract
+# marker, which we will consider to be an error just to make sure that the
+# author didn't forget to add one. If the entire post is to be considered
+# part of the abstract, then the marker can be added at the end of the post.
+ENDFILE {
+ print "error: missing '<!-- more -->'" > "/dev/stderr"
+ exit 1
+}
diff --git a/src/posts.sh b/src/posts.sh
new file mode 100755
index 0000000..a3c6182
--- /dev/null
+++ b/src/posts.sh
@@ -0,0 +1,103 @@
+#!/bin/bash
+# Generate posts HTML page
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# The generated page contains the abstracts of _all_ posts; this may get
+# unwieldy over time.
+#
+# TODO: Maybe refactor common abstract logic with `index.sh' and
+# `papers.sh'?
+##
+
+set -euo pipefail
+
+# Last generated yet (see `abstract-from').
+declare -i lastyear=0
+
+
+# Get the file name of the Nth most recent post. This relies on the
+# existence of `post/list'.
+pnfile()
+{
+ local -ri n=${1?Missing relative post number}
+
+ sed "${n}q;d" post/list
+}
+
+
+# Read field FIELD from post metadata recfile FILE.
+pmeta()
+{
+ local -r file=${1?Missing file name}
+ local -r field=${2?Missing field name}
+
+ recsel -P "$field" "$file"
+}
+
+
+# Generate HTML for relative post number N (see `pnfile').
+abstract-from()
+{
+ local -r file=${1?Missing post file name}
+
+ local title date slug body
+ title=$( pmeta "$file" subject )
+ date=$( pmeta "$file" date )
+ slug=$( pmeta "$file" slug )
+ body=$( pmeta "$file" abstract )
+
+ local -ri year=${date:0:4}
+
+ if [ $year -ne $lastyear ]; then
+ test $lastyear -eq 0 || echo '</section>'
+ lastyear=$year
+
+ cat <<EOF
+<section class="compact">
+<h1>$year</h1>
+EOF
+ fi
+
+ cat <<EOF
+<article class="abstract">
+ <h2 class="title"><a href="$slug">$title</a></h2>
+ $body
+ <p class="date">Posted on $date.
+ <a href="$slug">Read more &raquo;</a>
+ </p>
+</article>
+EOF
+}
+
+
+# Generate posts page.
+main()
+{
+ src/mkheader posts Posts
+
+ local file
+ while read file; do
+ abstract-from "$file"
+ done < post/list
+
+ echo '</section><br class="end" />'
+
+ cat src/footer.tpl.htm
+}
+
+
+main "$@"
diff --git a/src/rss.sh b/src/rss.sh
new file mode 100755
index 0000000..5fb506f
--- /dev/null
+++ b/src/rss.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+# Generate RSS feed from given post metadata files
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# All posts must be provided on the command line as a path to each
+# individual metadata file, in the order in which they should appear in the
+# feed output.
+##
+
+set -euo pipefail
+
+# Website root URL.
+declare -r www=${WWW_URL:-https://mikegerwitz.com}
+
+
+# Look up metadatum FIELD in metafile FILE.
+pmeta()
+{
+ local -r file=${1?Missing metafile name}
+ local -r field=${2?Missing field name}
+
+ recsel -P "$field" "$file"
+}
+
+
+# Generate RSS item for each post in provided arguments.
+# See `gen-item'.
+gen-items()
+{
+ while [ $# -gt 0 ]; do
+ gen-item "$1"
+ shift
+ done
+}
+
+
+# Generate RSS item for post in metadata file FILE. The abstract will be
+# used for the item description.
+gen-item()
+{
+ local -r file=${1?Missing file name}
+
+ local subject author slug date
+ subject=$( pmeta "$file" subject )
+ author=$( pmeta "$file" author )
+ slug=$( pmeta "$file" slug )
+ date=$( pmeta "$file" date )
+
+ # TODO: entire content?
+ local abstract
+ abstract=$( pmeta "$file" abstract )
+
+ cat <<EOF
+<item>
+ <title><![CDATA[$subject]]></title>
+ <author><![CDATA[$author]]></author>
+ <link>$www/$slug</link>
+ <pubDate>$date</pubDate>
+ <description><![CDATA[$abstract]]></description>
+</item>
+EOF
+}
+
+
+# Output usage information and exit with EX_USAGE.
+usage()
+{
+ cat <<EOF
+Usage: $0 postmeta...
+Generate RSS feed from provide post metadata.
+Example: $0 post/2018-01-01-foo.meta post/2018-02-01-bar.meta
+
+At least one postmeta must be provided.
+EOF
+
+ exit 64 # EX_USAGE
+}
+
+
+# Output RSS feed from all post files provide via arguments.
+main()
+{
+ test $# -gt 0 || usage
+
+ cat <<EOF
+<?xml version="1.0"?>
+<rss version="2.0">
+ <channel>
+ <title>Mike Gerwitz's Thoughts and Ramblings</title>
+ <link>$www</link>
+ <description>
+ Posts and articles from a free software hacker and activst with a focus on user privacy and security
+ </description>
+ $( gen-items "$@" )
+ </channel>
+</rss>
+EOF
+}
+
+
+main "$@"
diff --git a/src/talks.rec b/src/talks.rec
new file mode 100644
index 0000000..3591e88
--- /dev/null
+++ b/src/talks.rec
@@ -0,0 +1,81 @@
+id: sapsf
+title: The Surreptitious Assault on Privacy, Security, and Freedom
+location: LibrePlanet 2017
+date: 2017-03-26
+locimg: lp-2017
+abstract: Privacy, security, and personal freedom: one cannot be had without the
++ others. Each of these essential rights are being surreptitiously
++ assaulted; only the most technical among us even know what to look for,
++ let alone how to defend ourselves. Governments, corporations, and groups
++ of ill-minded individuals are spying and preying upon both users and
++ bystanders with unprecedented frequency and breadth. For those of us who
++ do understand these issues, it would be irresponsible not to fight for
++ the rights of others and continue to bring these assaults to light.
++
++ This talk will survey the most pressing issues of today, including
++ topics of government surveillance and espionage; advertisers and data
++ analytics; the Internet of Things; corporate negligence; public policy
++ and the crypto wars; dangers of a non-free Web and untrusted, ephemeral
++ software; pervasive monitoring; remote servers, services, and “the
++ cloud”; modern vehicles; the fight against decentralization and free
++ software; societal pressures and complacency with the status quo; and
++ more.
++
++ Attendees will walk away with a broad understanding of these topics; an
++ overview of mitigations; and dozens of resources for further research
++ and discussion with others. No prior knowledge of security or
++ cryptography are necessary.
+video-url: https://media.libreplanet.org/u/libreplanet/m/the-surreptitious-assault-on-privacy-security-and-freedom/
+link: /talks/sapsf.pdf Slides
+link: /projects/sapsf/plain/sapsf.bib Bibliography
+link: /projects/sapsf/ Source Code
+
+
+id: ethics-void
+title: The Ethics Void
+location: LibrePlanet 2018
+date: 2018-03-25
+locimg: lp-2018
+abstract: Many communities have widely adopted codes of ethics governing the
++ moral conduct of their members and professionals. Some of these codes may
++ even be enshrined in law, and for good reason—certain conduct can have
++ enormous consequences on the lives of others.
++
++ Software and technology pervade virtually every aspect of our lives. Yet,
++ when compared to other fields, our community leaders and educators have
++ produced an ethics void. Last year, I introduced numerous topics concerning
++ privacy, security, and freedom that raise serious ethical concerns. Join me
++ this year as we consider some of those examples and others in an attempt to
++ derive a code of ethics that compares to the moral obligations of other
++ fields, and to consider how leaders and educators should approach ethics
++ within education and guidance.
+video-url: https://media.libreplanet.org/u/libreplanet/m/the-ethics-void/
+link: /talks/ethics-void.pdf Slides
+link: /projects/ethics-void/ Source Code
+
+
+id: online-freedom
+title: Restore Online Freedom!
+location: LibrePlanet 2016
+date: 2016-03-20
+locimg: lp-2016
+abstract: Imagine a world where surveillance is the default and users must
++ opt-in to privacy. Imagine that your every action is logged and analyzed to
++ learn how you behave, what your interests are, and what you might do
++ next. Imagine that, even on your fully free operating system, proprietary
++ software is automatically downloaded and run not only without your consent,
++ but often without your knowledge. In this world, even free software cannot
++ be easily modified, shared, or replaced. In many cases, you might not even
++ be in control of your own computing—your actions and your data might be in
++ control by a remote entity, and only they decide what you are and are not
++ allowed to do.
++
++ This may sound dystopian, but this is the world you’re living in right
++ now. The Web today is an increasingly hostile, freedom-denying place that
++ propagates to nearly every aspect of the average users’ lives—from their PCs
++ to their phones, to their TVs and beyond. But before we can stand up and
++ demand back our freedoms, we must understand what we’re being robbed of, how
++ it’s being done, and what can (or can’t) be done to stop it.
+video-url: https://media.libreplanet.org/u/libreplanet/m/restore-online-freedom/
+link: https://media.libreplanet.org/u/libreplanet/m/restore-online-freedom-14bf/ Slides
+link: /projects/online-freedom/ Source Code
diff --git a/src/talks.sh b/src/talks.sh
new file mode 100755
index 0000000..15f87dd
--- /dev/null
+++ b/src/talks.sh
@@ -0,0 +1,101 @@
+#!/bin/bash
+# Generate talks HTML page
+#
+# Copyright (C) 2019 Mike Gerwitz
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+# Talks are organized along with abstract in $TALKFILE. Abstracts are
+# assumed to be Markdown-formatted and are run through Pandoc. A link to
+# the talk video is provided, along with any supplemental links provided via
+# $TALKFILE (e.g. slides, source code, bibliography).
+##
+
+set -euo pipefail
+
+# Recfile containing talk abstracts and metadata.
+declare -r TALKFILE=${TALKFILE:-src/talks.rec}
+
+
+# List ids of all talks in $TALKFILE.
+talk-list()
+{
+ recsel -CP id "$TALKFILE"
+}
+
+
+# Retrieve field FIELD from talk identified by ID in $TALKFILE.
+talk-field()
+{
+ local -r id=${1?Missing talk id}
+ local -r field=${2?Missing talk field}
+
+ recsel -P "$field" -e "id = '$id'" "$TALKFILE"
+}
+
+
+# Generate abstract for talk.
+abstract()
+{
+ local -r id=${1?Missing talk id}
+
+ local title location locimg date abstract url links
+ title=$( talk-field "$id" title )
+ location=$( talk-field "$id" location )
+ locimg=$( talk-field "$id" locimg )
+ date=$( talk-field "$id" date )
+ abstract=$( talk-field "$id" abstract )
+ url=$( talk-field "$id" video-url )
+ links=$( talk-field "$id" link )
+
+ local abstract_html
+ abstract_html=$( pandoc -fmarkdown -thtml5 <<< "$abstract" )
+
+ cat <<EOF
+<article class="abstract talk">
+ <h2 class="title" id="$id">$title</h2>
+
+ <ul class="links">
+ <li><a class="video $locimg" href="$url">Watch $location Talk</a></li>
+ $(
+ while read lurl ltitle; do
+ printf "<li><a href="%s">%s</a></li>\n" "$lurl" "$ltitle"
+ done <<< "$links"
+ )
+ </ul>
+
+ $abstract_html
+
+ <p class="date">Presented on $date.</p>
+</article>
+EOF
+}
+
+
+# Generate talks page.
+main()
+{
+ src/mkheader talks Talks
+
+ local talks
+ talks=$( recsel -P id src/talks.rec )
+
+ echo '<h1>Talks</h1>'
+ talk-list | while read id; do abstract "$id"; done
+
+ cat src/footer.tpl.htm
+}
+
+
+main "$@"
diff --git a/style.css b/style.css
index d13c4e5..bba5f6c 100644
--- a/style.css
+++ b/style.css
@@ -1,111 +1,186 @@
+/**
+ * mikegerwitz.com stylesheet
+ *
+ * Copyright (C) 2019 Mike Gerwitz
+ * This work is released under the Creative Commons Attribution
+ * Share-Alike 4.0 International license.
+ */
+
+/* TODO: Good font stack to fall back on if user has fonts blocked. */
@font-face {
- font-family: Open Sans;
- src: url('/fonts/OpenSans-Regular.woff');
+ font-family: Source Sans Pro;
+ src: url('/fonts/SourceSansPro-Regular.otf.woff');
+}
+@font-face {
+ font-family: Source Sans Pro Light;
+ src: url('/fonts/SourceSansPro-Light.otf.woff');
+}
+
+html {
+ /* see footer; just in case the page is too short */
+ background-color: #2e3436;
}
body {
- margin: 1em 5em;
+ background-color: white;
+
+ /* TODO: slightly non-black color */
+
+ margin: 0;
+ padding: 2em 4em 0em 4em;
+ /*padding: 1em 5em;*/
+
text-align: justify;
- font-family: 'Open Sans', 'Liberation Sans', sans-serif;
+ font-family: 'Source Sans Pro', 'Liberation Sans', sans-serif;
}
-body.index,
-.body-index {
- margin: 2em 10em 1em 10em;
- padding-right: 300px;
-}
+a { color: #0066cc; }
+a:visited { color: #6666cc; }
-/* override above, since we'll have to compound
- * with the original body (only use this when
- * body.index cannot possibly be used!) */
-.body-index {
- margin: 2em 5em 1em 5em;
+.title > a {
+ color: black;
+ text-decoration: none;
}
-body.index.no-sidebar,
-.body-index.no-sidebar {
- padding-right: 0px;
-}
+a.box {
+ display: block;
+ width: 200px;
+ padding: 204px 0 0 0;
-a { color: #0066cc; }
-a:visited { color: #6666cc; }
+ border-width: 4px;
+ border-style: solid;
+ border-color: #2e3436;
-/* hanging; ids for asciidoc styling */
-header, footer,
-#header, #footer, .article #copyright {
- margin: 0em -3em;
- text-align: left;
+ background-color: #2e3436;
+ color: white;
+
+ background-repeat: no-repeat;
+ background-size: contain;
+
+ text-align: center;
+ font-weight: bold;
+ font-size: 1.2em;
+
+ text-decoration: none;
}
-body.index footer,
-.body-index footer {
- margin: 0em -10em;
+a.box:hover {
+ border-top-width: 8px;
+ padding-top: 200px;
+ background-position: 0px -4px;
}
-/* typesetting standards for ~60 chars per line */
-body article .content,
-body.article #content {
- clear: both;
- margin: auto;
+a.box:visited {
+ color: white;
+}
- max-width: 38em; /* fallback for older browsers */
- max-width: 60ch;
- line-height: 1.8em;
+/* Asides should be dimmed so as not to distract from
+ the main content. */
+aside a.box {
+ filter: grayscale(100%);
+ transition: filter 0.25s;
}
-/* ~70 for certain articles because of nesting (like GHS) */
-body.article #content {
- max-width: 44em; /* fallback for older browsers */
- max-width: 70ch;
+aside a.box:hover {
+ filter: none;
}
-body article header,
-body.article #header {
- margin: auto;
- max-width: 44em; /* fallback for older browsers */
- max-width: 70ch;
+
+/* Link lists are to be styled in context-specific ways. */
+ul.links {
+ display: block;
+ padding: 0;
+ margin: 0;
+ text-align: center;
+}
+ul.links > li {
+ display: block;
+ margin-top: 1em;
+}
+ul.links > li:first-child {
+ margin-top: 0;
}
-h1, h2, h3, #menu,
-body.index ul.index li .day,
-.author,
-strong {
- font-family: 'URW Gothic L', 'Avant Garde', sans-serif;
- font-weight: normal;
+
+.talk ul.links {
+ display: inline-block;
}
-h1 { font-size: 1.8em; }
-h2 { font-size: 1.4em; }
-h2.date {
+/* Talk images */
+.talk .links a.video {
display: block;
- font-size: 1.1em;
- color: #666f63;
+ background-repeat: no-repeat;
- margin: -1em 1.5em 1.5em 0em;
- float: left;
+ line-height: 2em; /* some space below image */
+}
+.talk .links a.video.lp-2016 {
+ background-image: url('images/lp-2016.png');
+ padding-top: 75px;
+ min-width: 220px;
+}
+.talk .links a.video.lp-2017 {
+ background-image: url('images/lp-2017.png');
+ padding-top: 75px;
+ min-width: 220px;
+}
+.talk .links a.video.lp-2018 {
+ background-image: url('images/lp-2018.png');
+ padding-top: 97px;
+ min-width: 200px;
}
-h2.date ~ .author {
- display: block;
- margin-top: -1em;
+
+a.box.free-sw {
+ background-image: url('images/tp/fsfs-icons-beige.png');
+}
+a.box.eff-privacy {
+ background-image: url('images/tp/eff-privacy.png');
+}
+
+
+main {
+ position: relative;
}
-.author > .email {
- margin-left: 0.25em;
+main > aside {
+ float: right;
}
+aside.sm {
+ max-width: 30ch;
+ font-size: 0.9em;
+}
+
+
+h1, h2, h3 {
+ font-weight: normal;
+}
+
+h1 { font-size: 1.7em; }
+h2 { font-size: 1.4em; }
+h3 { font-size: 1.1em; }
+h4 { font-size: 1.0em; }
+
h1 a, h1 a:visited {
text-decoration: none;
color: inherit;
}
-/* latter for asciidoc-generated output */
-h1.title,
-#header h1 {
+
+header {
+ position: relative;
+ margin: 0 0 2em 0;
+}
+
+header h1 {
font-size: 2em;
- margin-bottom: 0.1em;
+ margin: 0px 0px 0.1em 0px;
+ text-align: left;
+}
+
+.title {
text-align: left;
}
@@ -116,124 +191,194 @@ h2.desc {
font-weight: normal;
color: #666f63;
- margin-top: 0px;
- margin-bottom: 2em;
+ margin: 0px 0px 2em 0px;
+}
+
+header nav {
+ position: absolute;
+ top: 0;
+ right: 0;
}
-#menu {
+.menu ul {
+ display: inline-block;
text-align: center;
padding: 0;
- margin: 0px -300px 3.5em 0px;
-}
-.no-sidebar #menu {
- /* cancels out #menu padding above */
- margin-right: 0px;
+ margin: 0;
+
+ /* height of h1 to the left */
+ line-height: 2em;
}
-#menu li {
+.menu li {
display: inline-block;
- font-size: 1.3em;
- letter-spacing: 0.05em;
-
- /* in addition to the 3.5em above; allows
- for decent spacing when line overflows
- at lower resolutions
- (3.5 + [0.5/1.3=0.38] = 4.0)*/
- margin-bottom: 0.38em;
+ font-size: 1.1em;
+ font-weight: bold;
}
-#menu li a {
- color: #666f63;
+.menu li a {
+ color: #2e3436;
text-decoration: none;
- border-left: 1px solid #868f83;
padding: 0.15em 1em;
}
-#menu li:first-child a {
- border-left: none;
+.menu li a:hover {
+ border-bottom: 0.3ex solid #2e3436;
}
-#headline {
- position: absolute;
- text-align: center;
- right: 10em;
+
+main {
+ margin: auto;
+ width: 90ch;
}
-#headline a {
- display: block;
- text-decoration: none;
- margin-top: 2em;
- clear: left;
+
+body.posts main {
+ width: auto;
+ max-width: 120ch;
}
-#headline a:first-child {
- margin-top: 0;
+
+
+/* Articles are formatted at a modest width that makes reading
+ easier. Reduced with makes it easier for the reader's eyes to scan to
+ the next line. Alternatively, the line spacing can be increased to make
+ it easier for the eyes to not loose their way. So the wider the text,
+ the larger the line spacing. */
+
+article {
+ width: 70ch;
+ line-height: 1.8em;
+ margin: auto;
}
-#headline img {
- margin-left: 2em;
+article.abstract {
+ width: 60ch;
+ line-height: 1.5em;
+ margin: 0;
}
-body.index .content,
-.body-index .content {
- /* this is not ideal, but works since the sidebar content is (currently) all
- images */
- min-height: 750px;
- padding-right: 1.5em;
+/* Main links appear to the right of the abstract. */
+article.abstract ul.links {
+ position: absolute;
+ right: 0;
+ min-width: 25ch;
+}
- /* don't let text get too wide */
- max-width: 40em;
- margin: auto;
- line-height: 1.8em;
+article.abstract .title {
+ display: inline-block;
+ margin: 0;
+ font-weight: bold;
+ font-size: 1.1em; /* h3 */
+ text-align: left;
+}
+
+article:not(.abstract) > hgroup {
+ margin: 0 -2rem;
}
-#cgit .content {
- max-width: none;
+article:not(.abstract) > h1:not(:first-child),
+article:not(.abstract) > h2 {
+ margin-left: -2rem;
+ border-bottom: 2px solid #babdb6;
}
-body.index.no-sidebar .content,
-.body-index.no-sidebar .content {
- min-height: inherit;
+article:not(.abstract) > h3 {
+ border-bottom: 1px solid #babdb6;
}
-body.index h3.index {
- margin-bottom: 0.5em;
+article .date {
+ font-size: 0.9em;
+ color: #666f63;
+ margin-top: -1em;
}
-body.index ul.index {
- text-align: left;
- list-style: none;
- margin: 0px;
- padding-left: 1.5em;
+
+article.abstract {
+ margin-top: 1em;
}
-body.index ul.index li {
- margin: 1em 0px;
+
+article.abstract p:first-of-type {
+ margin-top: 0;
}
-body.index ul.index li .day {
+
+/* Images are all centered by default. */
+article img {
+ display: block;
+ margin: 0 auto;
+}
+
+
+section.compact {
+ clear: both;
+}
+
+section.compact article {
+ width: 48%;
+ float: right;
+}
+
+/* the first child is the section heading, so odds should
+ be on the left */
+section.compact article:nth-child(2n) {
float: left;
- margin-right: 0.5em;
+ clear: both;
}
-p#ref-0 {
- margin-top: 2em;
+
+/* posts */
+body.posts section.compact:not(:first-child) {
+ padding-top: 2em;
}
-p.ref {
- font-size: 0.9em;
- margin: 0.25em 0em;
- text-align: left;
+body.posts section.compact > h1 {
+ text-align: center;
}
-sup {
- font-size: 0.6em;
+
+
+section .view-all {
+ display: block;
+ text-align: center;
+ margin: 1em auto;
+ clear: both;
}
-p.ref:target {
- background-color: #fce94f;
+
+
+section.highlight {
+ display: block;
+ background-color: #2e3436;
+ padding: 2em;
+ color: #eeeeee; /* just slightly less jarring */
+ margin: 2em 0;
+ clear: both;
}
-pre {
- white-space: pre-wrap;
+section.highlight > .title {
+ font-size: 1.2em;
+ display: inline-block;
+ width: 50%;
+ font-weight: bold;
+ margin-top: 0;
}
-dt {
- letter-spacing: 0.1em;
+section.highlight aside {
+ display: block;
+ float: right;
+ width: 40%;
+
+ font-family: 'Source Sans Pro Light';
+ font-size: 0.9em;
}
-tt {
- background-color: #eeeeec;
- color: #000055;
+section.highlight a.lp-watch {
+ display: inline-block;
+
+ background-image: url('images/tp/lp-2017-crop.png');
+ background-repeat: no-repeat;
+ background-position: middle left;
+
+ /* accommodate background image */
+ line-height: 75px;
+ padding-left: 85px; /* 75px + 10px margin between */
+
+ font-size: 1.2em;
+ color: white;
+
+ clear: left;
}
+
.inline-img {
text-align: center;
}
@@ -258,21 +403,8 @@ tt {
margin-left: auto;
}
-.listingblock {
- background-color: #eeeeec;
- background-image: url('images/cross_scratches.png');
- padding: 0.5em;
- border: 1px solid #babdb6;
- border-radius: 0.25em
-}
-
-.exampleblock {
- margin-left: 2em;
- padding-left: 1em;
- border-left: 5px solid #eeeeec;
-}
-#gnuinside {
+.page-flip {
position: absolute;
display: block;
@@ -282,106 +414,51 @@ tt {
height: 50px;
}
-footer, #footer, .article #copyright {
- font-size: 0.9em;
- margin-top: 2em;
- clear: both;
-}
-
-footer .commit-id {
- font-family: monospace;
-}
-
-/* to account for headline (sidebar) */
-body.index footer .bimgs,
-.body-index footer.bimgs,
-body.index footer hr,
-.body-index footer hr {
- margin-right: -300px;
-}
-.no-sidebar footer .bimgs,
-.no-sidebar footer hr {
- margin-right: 0px;
+.affiliation-list ul {
+ display: inline-block;
+ text-align: center;
+ padding: 0;
+ margin: 0;
}
-
-#selflinks {
- position: absolute;
- top: 60px;
- right: 0px;
- width: 42px;
- padding: 6px;
+.affiliation-list ul > li {
+ display: inline-block;
+ margin: 1em;
}
-#selflinks a {
+.affiliation-list a {
text-decoration: none;
}
-#selflinks img {
- transition: transform 0.25s;
-}
-#selflinks img[src*=octoright]:hover {
- transform: rotate(-20deg);
-}
-
-.octoflop {
- /* make upright again (image is rotated 270deg) */
- transform: rotate(90deg);
-
- animation-duration: 2s;
- animation-delay: 2s;
- animation-name: octoflop;
- animation-fill-mode: forwards;
-}
-
-.talk-logo {
- display: block;
- text-align: center;
+.affiliation-list img:not(:hover) {
+ transition: filter 3s;
+ filter: grayscale(100%);
}
-
-p ~ p .talk-logo {
- margin-top: 5ex;
+.affiliation-list img[src*=octoright] {
+ transition: transform 0.5s;
}
-
-@keyframes octoflop {
- 30% {
- transform: rotate(-35deg);
- }
- 50% {
- transform: rotate(25deg);
- }
- 65% {
- transform: rotate(-17deg);
- }
- 75% {
- transform: rotate(10deg);
- }
- 85% {
- transform: rotate(-5deg);
- }
- 90% {
- transform: rotate(3deg);
- }
- 95% {
- transform: rotate(-2deg);
- }
- 100% {
- transform: rotate(0deg);
- }
+.affiliation-list img[src*=octoright]:hover {
+ transform: rotate(-20deg);
}
.hn-icon {
- display: block;
+ display: inline-block;
+ position: relative;
background-color: #ff6600;
width: 42px;
height: 42px;
+ top: -1em;
font-size: 16px;
font-weight: bold;
text-align: center;
line-height: 42px;
}
+.hn-icon:not(:hover) {
+ transition: background-color 3s;
+ background-color: #888888;
+}
.hn-icon,
a.hn-icon:visited,
@@ -391,357 +468,115 @@ a.hn-icon:hover {
text-decoration: none;
}
-.bimgs {
- float: right;
- margin-left: 1em;
-}
-
-.bimgs img {
- margin-left: 0.1em;
-}
-.bimgs img:first-child {
- margin-left: 0em;
-}
-
-body.content .abstract {
- font-size: 0.9em;
-}
-body.content .abstract .start {
- font-weight: bold;
+br.end {
+ clear: both;
}
-dl > dd {
- margin-bottom: 0.5em;
+footer, footer h2 {
+ font-family: 'Source Sans Pro Light';
}
+footer, #footer {
+ font-size: 0.8em;
+ text-align: center;
-dl > dd > dl {
- margin-top: 1em;
-}
+ background-color: #2e3436;
+ color: #eeeeee;
-dl > dd > p:last-child {
- margin-bottom: 0px;
-}
+ margin: 4em -4rem 0 -4rem;
+ padding: 1em;
-#postamble > p {
- margin: 0em;
+ clear: both;
}
-#index-headline {
- display: block;
- margin: 0em auto 2em auto;
+#copyright {
+ width: 80ch;
+ margin: 1em auto 0em auto;
}
-#index-headline img {
- border-radius: 0.25em;
- max-width: 90%;
+footer .site-nav {
+ display: inline-block;
+ margin: 0 auto 1em auto;
}
-
-
-/** exclusively asciidoc-generated content styling **/
-body.article h2 {
- position: relative;
-
- border-bottom: 2px solid #babdb6;
- left: -2em;
-
- margin-right: -2em;
+footer .site-nav > nav {
+ text-align: left;
+ float: left;
+ margin: 0 2em;
}
-
-body.article h3 {
- border-bottom: 1px solid #babdb6;
+footer .site-nav > nav > h2 {
+ font-size: 1.2em;
+ margin: 0;
+ font-weight: bold;
}
-
-#author {
- font-size: 1.1em;
- letter-spacing: 0.1em;
+footer .site-nav > nav > ul {
+ display: inline-block;
+ padding: 0 0 0 0.5em;
+ margin: 0;
+ text-align: left;
}
-
-#footer {
- border-top: 2px solid #babdb6;
- padding-top: 0.5em;
+footer .site-nav > nav > ul > li {
+ display: block;
}
-
-.article #copyright {
- margin-top: 0;
+footer .site-nav > nav > ul > li a {
+ color: white;
+ text-decoration: none;
}
-@media screen and (max-width: 1024px) {
- body {
- margin: 2em !important;
- }
-
- /* account for upper-right page fold using the full
- image width---this will be guaranteed to work
- regardless of the user's font size; kinda ruins
- the illusion if text is atop of it ;) */
- h1.subject {
- margin-right: 50px;
- }
-
- #headline {
- right: 2em;
- }
- header, footer,
- #header, #footer, .article #copyright {
- margin-left: 0px;
- }
+.octoflop {
+ /* make upright again (image is rotated 270deg) */
+ transform: rotate(90deg);
- body.index footer,
- .body-index footer {
- margin: 0em;
- }
+ animation-duration: 2s;
+ animation-delay: 2s;
+ animation-name: octoflop;
+ animation-fill-mode: forwards;
}
-@media screen and (max-width: 640px) {
- body {
- margin: 1em !important;
- padding-right: 0 !important;
- }
- body.index .content,
- .body-index .content {
- min-height: 0px;
- padding-right: 0px;
- }
-
- header {
- margin-right: 0px;
- }
-
- #menu {
- margin-right: 0px;
- margin-bottom: 2em;
- }
-
- #headline {
- position: initial;
- float: right;
- width: 75px;
- }
-
- #headline a {
- display: inline;
- margin: 0.5em;
- }
- #headline img {
- max-height: 75px;
- margin-left: 0;
- }
- #index-headline img {
- max-height: 5em;
- }
-
- #selflinks {
- position: absolute;
- top: 0px;
- right: 50px;
- width: auto;
- height: 42px;
- padding: 6px;
- }
-
- .hn-icon {
- float: right;
- margin-left: 2px;
- }
-
- header, footer,
- body.index footer .bimgs,
- .body-index footer .bimgs,
- body.index footer hr,
- .body-index footer hr,
- #header, #footer, .article #copyright {
- margin-right: 0px;
- }
-
- .bimgs {
- float: none;
- margin-left: 0px;
- }
-
- /* we're pretty low on real estate at this point */
- blockquote {
- margin: 1em 0px 1em 2em;
- }
-
- ul, ul.index {
- padding-left: 1em !important;
+@keyframes octoflop {
+ 30% {
+ transform: rotate(-35deg);
}
-}
-
-/* selflinks start to overlap with heading */
-@media screen and (max-width: 475px) {
- #selflinks img {
- max-width: 32px;
- max-height: 32px;
+ 50% {
+ transform: rotate(25deg);
}
-
-
- .hn-icon {
- max-width: 32px;
- max-height: 32px;
-
- font-size: 12px;
- line-height: 32px;
+ 65% {
+ transform: rotate(-17deg);
}
-}
-
-/* when things start getting odd from 640px */
-@media screen and (max-width: 420px) {
- #menu {
- font-size: 0.8em;
+ 75% {
+ transform: rotate(10deg);
}
-
- #selflinks img {
- max-width: 21px;
- max-height: 21px;
+ 85% {
+ transform: rotate(-5deg);
}
-
- .hn-icon {
- max-width: 21px;
- max-height: 21px;
-
- font-size: 9px;
- line-height: 21px;
+ 90% {
+ transform: rotate(3deg);
}
-
- footer {
- font-size: 0.9em;
+ 95% {
+ transform: rotate(-2deg);
}
-
- .bimgs img {
- width: 70px;
- height: 25px;
+ 100% {
+ transform: rotate(0deg);
}
}
-/*** Org mode HTML output ***/
-/* much of the above will overlap, so only some is needed here */
-#postamble {
- margin: 2em -5em 0em -5em;
- text-align: left;
- font-size: 0.9em;
-
- border-top: 1px solid #babdb6;
- padding-top: 0.5em;
-}
-
-.todo, .done {
- font-size: 0.1em;
- letter-spacing: -0.1em;
- color: transparent;
-}
-
-/* note that we must undo our hiding */
-.todo::before,
-.done::before {
- position: absolute;
- visibility: visible;
-
- letter-spacing: normal;
- font-size: 12em;
- left: -1.5em;
- top: -0.1em;
-
- font-weight: bold;
-}
-
-.todo::before {
- color: black;
- content: '☐';
-}
-
-.done::before {
- color: #4e9a06;
- content: '☑';
-}
-
-/* eases positioning in, e.g., margin */
-.outline-1,
-.outline-2,
-.outline-3 {
- position: relative;
-}
-
-#table-of-contents .todo,
-#table-of-contents .done {
- display: none;
-}
-
-
-/** cgit customization **/
-
-div#cgit div.content {
- padding: 2em 0em; /* remove left/right margin */
-}
-
-/* repo name and desc, above tabs */
-div#cgit table#header td.main {
- font-size: 1.4em; /* h2 font size (see above) */
-}
-div#cgit table#header td.sub {
- border-top: 0px;
-}
-
-div#cgit #header {
- margin: inherit; /* undo previous conflicting style */
-}
-
-/* reduce tab page separator height */
-div#cgit table.tabs {
- border-bottom-width: 1px;
-}
-div#cgit table.tabs td a {
- padding: 0.25ex 0.75em 0ex;
-}
-div#cgit table.tabs td a.active {
- background-color: inherit;
- border-bottom: 3px solid #ccc;
-}
-
-div#cgit div.content {
- border-bottom: inherit; /* we have our own footer */
-}
-
-/* we have limited width, so wrap and compensate */
-div#cgit table.list.nowrap td {
- white-space: inherit;
- text-align: left;
-}
-div#cgit table.list.nowrap td.sublevel-repo,
-div#cgit table.list.nowrap td .age-months {
- white-space: nowrap;
-}
-div#cgit table.list.nowrap tr {
- vertical-align: top;
-}
-
-div#cgit table.list tr:not(.nohover) td {
- padding-top: 0.5ex;
- padding-bottom: 0.5ex;
-}
-
-/* getting creative...separate sections */
-div#cgit table.list tr:not(.nohover) + tr.nohover td {
- padding-top: 1ex;
-}
-
-/* reduce headings relative to surrounding page */
-div#cgit h1 { font-size: 1.4em; }
-div#cgit h2 { font-size: 1.2em; }
-div#cgit h3 { font-size: 1.1em; }
-div#cgit h4 { font-size: 1.0em; }
-
-
-/*** https://github.com/jgm/highlighting-kate/blob/master/css/hk-tango.css * ***/
+/*** https://github.com/jgm/highlighting-kate/blob/master/css/hk-tango.css ***/
+/* GNU GPLv2 */
/* Loosely based on pygment's tango colors */
+/* Modified where indicated by Mike Gerwitz */
table.sourceCode, tr.sourceCode, td.sourceCode, table.sourceCode pre
{ margin: 0; padding: 0; border: 0; vertical-align: baseline; border: none; background-color: #f8f8f8 }
td.nums { text-align: right; padding-right: 5px; padding-left: 5px; background-color: #f0f0f0; }
td.sourceCode { padding-left: 5px; }
code.sourceCode { background-color: #f8f8f8; }
-pre.sourceCode { background-color: #f8f8f8; line-height: 125% }
+pre.sourceCode {
+ /* modified by Mike Gerwitz */
+ padding: 1em;
+ margin: 0 -1em;
+
+ background-color: #f8f8f8;
+ line-height: 125%
+}
td.nums pre { background-color: #f0f0f0; line-height: 125% }
code.sourceCode span.kw { color: #204a87; font-weight: bold } /* Keyword */
code.sourceCode span.dt { color: #204a87 } /* Keyword.Type */