It’s more likely than you think.
Today I set up my website for blogging. I’m using the nanoc static site
generator, which I also use to render pages like my movies page with a bunch
of gross Ruby code. To set up nanoc for blogging I mostly followed this guide.
For the estimated reading time in my article subtitle, I was inspired by this
post but I greatly simplified the code as follows:
def reading_time(text)
words = text.split.size
wpm = 200.0
mins = (words / wpm).ceil
if mins == 1
'~1 minute'
else
"~#{mins} minutes"
end
end
Syntax highlighting
Speaking of code, setting up syntax highlighting was more work than I expected.
I found out that kramdown only supports highlighting Rust code through
Rouge, and Rouge’s Rust parser failed badly on the very first thing I tried.
At the time of writing, the lifetimes were marked with CSS .err
classes and
highlighted in red. Lifetimes are everywhere in Rust!
Instead of attempting to fix Rouge, I found a way to switch to good old
Pygments. It turns out nanoc has support for a filter that parses HTML and
syntax highlights code in <code class="language-foo">
tags using Pygments.
Fortunately, I can disable kramdown’s syntax highlighting and
make it emit exactly that, with proper language-foo
classes and all.
It’s a somewhat convoluted process, but I now have proper Rust highlighting!
Here’s a sample:
/// An iterator wrapping a `std::str::Chars` iterator which also keeps track of
/// the current line and column position.
#[derive(Clone)]
struct CharsPos<'a> {
chars: Chars<'a>,
pos: Pos,
}
impl<'a> Iterator for CharsPos<'a> {
type Item = char;
fn next(&mut self) -> Option<char> {
let opt_c = self.chars.next();
match opt_c {
Some('\n') => { self.pos.line += 1; self.pos.column = 1; }
Some(_) => { self.pos.column += 1; }
None => {}
}
opt_c
}
}
Incidentally, I’ve been dabbling with Perl 6 lately and finding that it has a
lot of fun, wacky features. It turns out Rouge doesn’t support Perl 6 at all.
Luckily for me, Pygments does, so I guess I’ll drop a random sample of that,
too:
sub format-duration(Int $milliseconds where * >= 0) returns Str {
my ($ms, $s, $m, $h, $d) = $milliseconds.polymod(1000, 60, 60, 24);
my $ms-hundreds = ($ms / 100).round;
if $d {
"{$d}d {$h}h {$m}m {$s}s"
} elsif $h {
"{$h}h {$m}m {$s}s"
} elsif $m {
"{$m}m {$s}s"
} else {
"{$s}.{$ms-hundreds}s"
}
}
LaTeX Math
Oh, and apparently kramdown supports \LaTeX math via MathJax. Let’s render
the Taylor series expansion of e^x, why not?
e^x
= \sum_{n = 0}^{\infty} {x^n \over n!}
= 1 + x + {x^2 \over 2!} + {x^3 \over 3!} + {x^4 \over 4!} + \cdots
Atom feed
I also use nanoc to generate an Atom feed for my blog posts, so you should be
able to throw my website into your feed aggregator if you’re one of those rare
people like me who still uses one.
Source code
Finally, the entire source code for my website, including this post, is
available on GitHub.
That’s all for now, folks.