I got drydock working in a large enough part to finally be able to output all the HTML files for this site. It’s not the most beautiful thing, at the moment:


But it’s working!

I’d like to get syntax coloring and LaTeX working before I start work on the frontend part. At the moment, I also don’t export static files to the output directory. After that’s done, I’ll need to figure out a way to compile SASS and minify the assets…

I might also need to rework the way I handle paths. Obsidian’s path handling is a bit funky—it doesn’t require qualifying references with the full path—and I could simplify the logic in my code a lot if I just implemented a resolve_name_to_path_relative and resolve_name_to_path_absolute.

Oh, the graphs aren’t working yet either.

A couple hours later and both LaTeX and code blocks are done!

Here’s a snippet of Rust to test syntax coloring:

fn build_reverse_tag_map(
    source_files: &HashMap<VaultPath, SourceFile>,
) -> HashMap<String, HashSet<VaultPath>> {
    let mut map = HashMap::new();
    for (path, source_file) in source_files {
        if let Some(page) = source_file.page() {
            for tag in &page.tags {

And here’s inlineLaTeXinline \LaTeX!

…Actually, now that I think about this, this might be easier to do with Zola. If I emit processed Markdown and rely on Zola for conversion to HTML, I won’t have to worry about SASS and all the other fun stuff.

It’s now 10PM and I’ve mostly rewritten drydock—now called spacedock—to use Zola. Turns out that Zola’s templating can be really annoying at times; there’s no way (that I can think of, at least) to reuse blocks, so I end up with all these blocks that have to be overridden for pages and sections separately:

HTML <head>:

  • meta_title
  • meta_description
  • imageurl (optional, has a default)
  • imagealt (optional, has a default)
  • html_title
  • headextra (optional, has a default)

Rendered in the post:

  • page_body
  • date
  • title
  • description
  • content

It is now 1AM and I’ve successfully abused Tera’s macros enough to build my own impromptu multilevel tag system on top of Zola. The site builds successfully using Zola as the backend now; I’ll need to integrate with its serve command (or implement my own).

The resulting HTML is actually further from the goal than yesterday’s was—spacedock doesn’t preprocess the Markdown sources in any way, including things as basic as resolving wikilinks—but I’ve saved a ton of time elsewhere. Zola gets me, for free:

  • Easily extensible syntax highlighting!
  • An Atom or RSS feed!
  • Individual tag pages and a listing of all tags, including direct references to the tagged pages and their count. Note to self: this is a good opportunity to throw an assert into the template to make sure my computed tag counts match the actual ones.
  • SASS compilation!
  • Finding dead internal links—I might need to do this in spacedock anyway though, if I want to have distinct styling for redlinks.
  • Drafts that are visible locally but don’t get included in builds!
  • Shortcodes!
  • A search index!

And all that for the small price of having to suffer through the site root being a different type than all the other pages.

Plan for tomorrow:

  • Implement spacedock serve
  • Preprocess Markdown sources:
    • Compile LaTeX
    • Compile Mermaid.js diagrams
    • Resolve wikilinks and ![[embeds]]
    • Check if pulldown-cmark supports:
      • Task lists
      • Footnotes1
      • Comments
      • Callouts
      • Highlights
      • Strikethrough
  • Export the tag and post connectivity graphs
  • …Build the entire frontend.

I’ve been working on this nonstop for 19 hours now. It’s definitely time to take a break 😌

It’s now 4:20 AM (🔥) and I’ve just implemented hot-reloading and serving.

I wonder if Zola would be any faster if I compiled it from source. Right now it builds in about 90ms.

Hm. Building zola with target-cpu=native is… slower by about 10-15%. Damn.

7:30 AM; I took a quick two-hour nap and am back at work implementing the Markdown preprocessing. Looks like pulldown-cmark does support task lists and footnotes, so that’s great.

I’m now realizing that I can preprocess all of these with fancy-regex, I don’t need a full-blown Markdown parser.

I ended up needing pulldown-cmark anyway. Turns out that comments inside code blocks:

like this

…don’t get stripped out (and thank the gods for that!). It took a lot of messing with lifetimes, but I eventually got it working 🎉 It is now 11:00 AM.

I’m running into an issue where it looks like spacedock is trying to restart Zola too quickly now, and it cannot grab the port it needs.

…Oh gods, I just checked btop and there’s a million billion Zola processes.

I gave up on using the stdlib std::process::Command module and grabbed the saner subprocess instead. That solved that problem.

Turns out Obsidian’s comment handling is really funky. “Partial” comments are valid in some contexts but not others; my parser is really messy and not quite compliant with Obsidian, but I don’t plan to use comments particularly heavily. They don’t render nicely in the edit view anyway.

It looks like Obsidian supports two kinds of LaTeX; $$ double dollar signs $$ turn into fullwidth display LaTeXfullwidth\ display\ \LaTeX, and $inline$ turns into inline LaTeXinline\ \LaTeX.

A linebreak terminates $inline latex$ but display latex can start and end in the middle of a line, so I’ll need to borrow some logic from the comment parser to handle that.

Good news—inline LaTeX\LaTeX now works!

It’s 12:30 AM.

I’d like to rewrite my NoteContentProcessor into an iterator that can add new events to the stream. Maybe I can get by with just using flat_map instead of filter_map?

Note to self: [brackets] get returned as individual Text events - i.e. [brackets] would be Text(Borrowed("[")) followed by Text(Borrowed("brackets")) and Text(Borrowed("]")). This might either make wikilink parsing a lot easier… or a lot harder. We’ll see.


Here’s a footnote.