Adding local search to Hugo with Pagefind

At this point, I have very nearly 2500 posts going back almost 20 years (… whoa). In a lot of ways, it’s a second brain for me. I actually find myself (from time to time) going back and looking up my various old posts.

Sometimes, I wanted to know how I solved a particular programming problem, sometimes I wanted to know when I went somewhere (by pictures!), and sometimes I wanted to know what a particular book or movie was about.

So for the longest time, I’ve had (up in the corner there) a nice search box. Powered by Google: Don’t Be Evil. Well, today, let’s see if we can do better!

read more...


Crosslinks by Title in Hugo--But Better!

Once upon a time, I solved Crosslinks by Title in Hugo. Back then, I added a shortcode so that I could link to any post by title like this:

{{< crosslink "Title goes here" >}}

It worked pretty well, but … it never really felt ‘Markdown’y. Which I suppose was the point.

But more recently, I came across Markdown render hooks.

What’s that you say? I can write code that will take the parameters to any Markdown link (or image/heading/codeblock) and generate the HTML with a custom template?

Interesting!

read more...


Local JS/CSS with Hugo Pipe

I recently stumbled across a post that reminded me that Hugo has pipes. You can use them to automatically download files and include them as local. This seems like a pretty good idea for JS/CSS (you can argue caching versus security/locality all you want), but I’m going to give it a try.

read more...


Go is faster than Python? (an example parsing huge JSON logs)

Recently at work I came across a problem where I had to go through a year’s worth of logs and corelate two different fields across all of our requests. On the good side, we have the logs stored as JSON objects (archived from Datadog which collects them). On the down side… it’s kind of a huge amount of data. Not as much as I’ve dealt with at previous jobs/in some academic problems, but we’re still talking on the order of terabytes.

On one hand, write up a quick Python script, fire and forget. It takes maybe ten minutes to write the code and (for this specific example) half an hour to run it on the specific cloud instance the logs lived on. So we’ll start with that. But then I got thinking… Python is supposed to be super slow right? Can I do better?

(Note: This problem is mostly disk bound. So Python actually for the most part does just fine.)

read more...


Crosslinks by Title in Hugo

Another quick Hugo post. One thing I miss about my previous blogging platform(s) was the ability to generate quick links between posts just by using the title of the post. So rather than this:

a cool post

This is [a cool post]({{< ref "2021-07-15-crosslinks-by-title-in-hugo" >}}), go read it.

You could do this:

This is {{< crosslink title="Crosslinks by Title in Hugo" text="a cool post" >}}.

Or shorter: {{< crosslink "Crosslinks by Title in Hugo" >}}.

And it should just work.

read more...


Generating a Book Bingo Chart in Hugo

Another r/Fantasy 2021 Book Bingo post! How in the world am I generating this (updating) chart in Hugo?

2021 Book Bingo

Attack on Titan, Vol. 1

by Hajime Isayama


Hard Mode ✓


5 SFF Short Stories (Hard: An entire anthology or collection)

The Poppy War

by R.F. Kuang


Hard Mode ✓


Set in Asia (Hard: by an Asian author)

The Changeling

by Victor LaValle


Hard Mode ✓


r/Fantasy A to Z Genre Guide (Hard: by a BIPOC author)

The House in the Cerulean Sea

by T.J. Klune


Hard Mode ✓


Found Family (Hard: featuring an LGBTQ+ character)

The Scorpio Races

by Maggie Stiefvater


Hard Mode ✓


First person POV (Hard: Multiple)

The Wyrmling Horde

by David Farland


r/Fantasy Book Club (Hard: with participation)

Replaced with: Sequel: Not the First Book in the Series (2017)

The Borrowers Afield

by Mary Norton


Hard Mode ✓


New to you author (Hard: haven’t heard much about)

Mexican Gothic

by Silvia Moreno-Garcia


Hard Mode ✓


Gothic Fantasy (Hard: not in the Book Riot article)

Transmetropolitan, Vol. 1: Back on the Street

by Warren Ellis


Hard Mode ✓


Backlist book (Hard: published before 2000)

Red Sister

by Mark Lawrence


Hard Mode ✓


Revenge-seeking character (Hard: revenge as the major book plot)

Six Wakes

by Mur Lafferty


Hard Mode ✓


Mystery plot (Hard: not primary world urban fantasy)

Wild Sign

by Patricia Briggs


Hard Mode ✓


Comfort read (Hard: that isn’t a reread)

Tales of Nezura: Book 1: The Zevolra

by Randall Cooper


Hard Mode ✓


Debut novel (Hard: published in 2021)

Hellblazer, Vol. 1: Original Sins

by Jamie Delano


Hard Mode ✓


Cat squasher (500+ pages; Hard: 800+ pages)

Daemon Voices

by Philip Pullman


Hard Mode ✓


SFF-related nonfiction (Hard: published in the last 5 years)

Cece Rios and the Desert of Souls

by Kaela Rivera


Hard Mode ✓


Latinx or Latin American author (Hard: with fewer than 1000 Goodreads ratings)

Black Rain and Paper Cranes

by R.S. Craig


Hard Mode ✓


Self published (Hard: with fewer than 50 Goodreads ratings)

Annihilation

by Jeff VanderMeer


Hard Mode ✓


Forest setting (Hard: for the entire book)

Gideon the Ninth

by Tamsyn Muir


Hard Mode ✓


Genre mashup (Hard: of three or more genres)

The Midnight Library

by Matt Haig


Hard Mode ✓


Has chapter titles of more than one word (Hard: for every chapter)

An Alchemy of Masques and Mirrors

by Curtis Craddock


Hard Mode ✓


___ of ___ (Hard: and ___)

Project Hail Mary

by Andy Weir


Hard Mode ✓


First contact (Hard: that doesn’t lead to war)

Black Sun

by Rebecca Roanhorse


Trans or Nonbinary (Hard: protagonist)

The Long Way to a Small, Angry Planet

by Becky Chambers


Hard Mode ✓


Debut author (Hard: with an AMA)

A Great and Terrible Beauty

by Libba Bray


Hard Mode ✓


Witches (Hard: as the main protagonist)

read more...


A Tabbed View for Hugo

One thing I’ve been using for a lot of my recent posts (such as Backtracking Worms) is a tabbed view of code that can show arbitrarily tabs full of code or other content and render them wonderfully! For example, we can turn: {{</*tabs*/>}} {{</*sourcetab ruby "examples/art-station.rune"*/>}} {{</*tab "art-station.svg"*/>}} {{</*include "output/art-station.svg"*/>}} {{</*/tab*/>}} {{</*sourcetab ruby "examples/astrology-and-moons.rune"*/>}} {{</*tab "astrology-and-moons.svg"*/>}} {{</*include "output/astrology-and-moons.svg"*/>}} {{</*/tab*/>}} {{</*sourcetab ruby "examples/text-circle.rune"*/>}} {{</*tab "text-circle.svg"*/>}} {{</*include "output/text-circle.svg"*/>}} {{</*/tab*/>}} {{</*/tabs*/>}} Into the tabbed example view at the end of yesterday’s post!

read more...


Prevent JavaScript links by parsing URLs

If you have a website that allows users to submit URLs, one of the (many many) things people will try to do to break your site is to submit URLs that use the javascript: protocol (rather than the more expected http: or https:). This is almost never something that you want, since it allows users to submit essentially arbitrary code that other users will run on click in the context of your domain (same origin policy).

So how do you fix it?

First thought would be to try to check the protocol:

> safe_url = (url) => !url.match(/^javascript:/)
[Function: safe_url]

> safe_url('http://www.example.com')
true

> safe_url('javascript:alert(1)')
false

read more...