I'm activating tech blog cliche #1 - a blog about how my blog works. The only mitigating factor I can offer in my defense is that the method is equal measures stupid and unique[1]: I just used C preprocessor macros.
An example of blog post source under this questionable system
I started off normal: I just used jekyll. However, around the fifth time I had annoying problems with my ruby install being out of date or broken when I tried to push a tweak to the site, I'd had enough. All I was using it for was to slap a bit of header and footer html on each page anyway, why did I need a whole language runtime and packaging system and pile of packages. An entire ecosystem of code to paste three strings together. I just needed a simple macro language, and as luck would have it, I already knew one.
I write C++ for a living, so I'm already using the C preprocessor every day. Why shouldn't I use it for this? Well, to be honest there's a few good reasons. The C preprocessor wasn't really designed for anything but C source, so it's a bit awkward to get it to stop "helping". I'm using gnu cpp (c preprocessor, /usr/bin/cpp, not c++) here, as my deployment target is a linux server. For a start, we need some special parameters:
If we don't take some care to remove built-in macros, we can get silly behaviour where some words in our body text are clobbered. Normally predefined macros have powerful, imposing names like __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8
, but sometimes they have rather more modest names like linux
or unix
, which are coincidentally rather likely to appear in a tech blog. This results in nonsense like "works on MacOS, Windows and 1", or "1 philosophy". Using -undef
does take care of most predefined macros, but a few C standard mandated ones remain. We can use -dM
to generate a header that #undef
s them, just in case I ever want to write a blog post about the detailed intricacies of __STDC_VERSION__
.
An elegant solution
So now you can just #include "header.html"
and you're off to the races. What's that you say? You need something fancy like an rss feed? Not a problem:
It's a mess and I love it. Using this crazy homebrew system hacked together out of wildly inappropriate tools just fills me with joy in a way no proper solution ever could. Here's the full script for completeness, in case anyone else wants to use it for some strange reason:
If you're on mobile, you might have noticed that the code snippets above don't require horizontal scrolling to read. Most of the time, people just use the <pre> tag for code snippets, and if they're feeling particularly generous they add some js to highlight the text inside the <pre>. The problem is that looks like absolute ass on mobile.
Can't see sheeeit
So if you're anything like me, you end up toggling on desktop mode:
Somewhat better
But that's not great either, because now all the text is small. The body text could wrap, that's not a problem. It's just the code that we need to keep strictly un-wrapped, but now we've scaled everything else down too and made it all hard to read. What we really want is to leave the body text alone, but have the code snippet font size automatically adjust to fit the longest line perfectly inside the viewport.
Until recently, my solution to that was a pretty bad one: I'd just screenshot the code in an IDE, and embed the screenshot. I can use css to scale the img tag to fit the viewport, and it all just works. On desktop it's rendered just fine, and on mobile the text is small, but small text is more readable than forced wrapping or horizontal scrolling. And if you really can't read it, you can always pinch-zoom and then use horizontal scrolling. Best of both worlds! But now I have an image of text instead of text, and that's nasty for a whole host of reasons.
Following a recent discussion on Lobste.rs about better code snippets in webpages, I decided to have a go at the solution proposed by xq: using an svg with embedded text. It's still text being rendered by the browser, so it won't get distorted when blown up, and it can be selected and copied[2], and I can use CSS to automatically scale it to fit the size of the viewport. That's what you've been reading above.
I used highlight.js to parse and highlight the code, then converted the <span> elements it generated into suitably annotated <tspan>s to be dumped inside an svg <text> element. If you're interested, you can check out the conversion tool here.
1: With a dash of misguided.
2: Well, kinda. There seems to be a bunch of issues with linebreaks in text elements in svgs. For example chrome and firefox seem to handle literal newlines differently, so I can't use them. In the end what I do is strip the newlines and use the "dy" attribute to force text down on the y axis at the start of every line. This means that if you copy the text the newlines aren't there, so I compensated by adding a copy text button that has the correct original text.