I’m occasionally asked how I put my site together. In short, AsciiDoc and MathJax. And for the pages that run code, I use a mix of Haskell compilers.
On some pages, there’s an Easter egg of sorts. Replace html with lhs in the
URL to see its source:
Other times, the secret extension is txt, such as the source of this page:
I have a few public repos containing the source of entire subsites, such as:
I’m neither a frontend engineer nor a web designer, but I find what I do works well enough.
I write best with a text editor using old-school text file and email conventions, such as minus signs or asterisks for list bullet points, and LaTeX notation for equations. The minimalist distraction-free environment makes me want to churn out line after line. Or maybe it subconsciously reminds me of long and glorious coding sessions, of heated debates on mailing lists, and of rushing to meet thesis deadlines, and I just go with the flow.
AsciiDoc turns classic text file flourishes into pretty HTML, and MathJax turns LaTeX into pretty equations rendered with JavaScript. I first encountered AsciiDoc when looking at Git documentation, and I wound up choosing it over its competitors for the same reasons Linus Torvalds did: it’s fairly well-defined and powerful, yet the source resembles the text files I once downloaded from BBS’s and studied on a 80x25 character terminal. (Though one annoying special case is tildes in URLs, like on this very page.)
A custom script named stitch automates building pages, and can be found
in my homebrew Haskell compiler repo,
which was the first subsite to use it. It deals with things like CSS; Google
Analytics; including a menu HTML file if appropriate. This lets me achieve my
ideal workflow: type, type, type, run script, type, type, type…
There was a time I wrote HTML by hand. Some old files may still lurk in dark corners of this website.
For mathematical symbols, I first used itex2MML, which defaults to LaTeX delimiters, that is, dollar signs for inline equations and backslash-square brackets for display equations.
I migrated to AsciiDoc with MathJax, which uses different delimiters, so for
backwards compatibility, I wrote a fragile script (cobble) so I could avoid
converting my old files and keep my old habits.
Then the original Python version of AsciiDoc was deprecated in favour of
Asciidoctor, which introduces yet more changes.
I decided backwards compatibility was a lost cause, and converted the source
files to Asciidoctor and MathJax. I still had to write a script (stitch) for
features such as menus, headers, footers, and links to next and previous
sections, but gone are the ad hoc parsers and delicate substitutions.
I was unable to escape parsers and substitutions completely. Like its
predecessor, the stitch script changes LaTeX-style code blocks
(\begin{code} and \end{code}) into AsciiDoc code blocks, so that the same
file can serve as a Haskell program as well as a webpage documenting the
program. I also wrote one-off scripts to generate the PDF version of
my number theory notes, as
I ran into many problems with Asciidoctor’s DocBook backend.
Stragglers may remain. Some equations might appear strange because they have been wrongly delimited, or text meant to be italic might instead appear in single quotes.
Older pages used the the Haste compiler to compile the Haskell featured on a webpage to produce JavaScript that demonstrate it. Conditional compilation lets me run the program locally as well as on the browser. The Haste compiler seems to have been abandoned.
I later used the Asterius compiler, which is now deprecated in favour of GHC. Asterius compiles to WebAssembly, which may mean better performance. Asterius worked well for a first-order logic theorem prover which Haste was unable to handle.
Then there are my own compilers. Though primitive, they produce small WebAssembly binaries. It can compile Haskell on the browser and run it and I’m proud it could handle an experimental PuzzleScript interpreter. Even though my compiler performs few optimizations, some of the interpreted games are playable. (Or perhaps it’s because modern machines and WebAssembly engines are so fast!)
One of my compilers acts as a (albeit buggy) interpreter, and I wrote
runme.js so the reader can edit code on the page and run it again. This
interactivity improves comprehension so I hope to migrate as much content as
possible to runme.js. My Haskell compiler is non-standard and produces slow
code, but:
Haskell veterans can easliy port my code to GHC anyway.
I no longer need to rely on others.
The interactive nature of runme.js helps me, too!
It makes it easier to develop webpages.
Gone is the lengthy compilation step when building my site. Instead, the browser compiles the code within the webpage.