fools-pyrite

computer toucher; RPG enjoyer


Are there any programming languages with:

  • sum types (unions / enums / ADTs)
  • non-null-references (eg Java fails, Typescript passes)
  • reasonable portability (Ideally a web target but solid Windows support is a must)
  • fast compilation speeds (TS and Rust both fail here, despite succeeding above)

Mostly I’m looking to hack around on small side projects and not super happy with any of the options I’ve tried



fools-pyrite
@fools-pyrite

When I GM an RPG, I accumulate a wiki full of notes about characters, locations, worldbuilding, and my future plans for them. I realized that wiki (minus the “future plans”) would be a useful resource for other players at the table. And given that I keep my notes in Markdown in Obsidian, how hard could it be to make them available as a website? Turns out to be not that bad at all

I have a private Github repo where everything takes place. There's a tiny shell script in there that pulls in the latest markdown files:

#!/bin/sh
rm -r src/
cp -r ~/wiki/campaign-notes/armour-astir/ ./src/

and a much beefier Typescript file that processes these Markdown files, which:

  1. Takes Obsidian's non-standard [[target|Description]] link syntax and make it the standard [Description](target)
  2. Hides everything below the first horizontal rule (--- in Markdown), to allow me to have secret and non-secret content close together
  3. Converts the Markdown to HTML
  4. Spits out that HTML (with appropriate links to styling etc) to disk

Then I push it up to Github, where a Github Action builds the site automatically and pushes it to a specific branch, which I have a Netlify site configured to watch.

All in all: I write my notes like I normally would, make sure to redact any secret information, and sync them into a git repo. One Rube Goldberg machine later, the players have a quick reference that includes what happened in each session, our collaborative world-building history, notable NPCs, etc.

If I ever write up part 2 I’ll talk about the dynamic star system map I coded up; that one is entirely self-indulgent lol

The typescript file is as follows (this is a total mess):

import fs from "fs";
import child_process from "child_process";
import jsdom from "jsdom";

// Run the obsidian-export tool over my notes
fs.mkdirSync("./intermediate", { recursive: true });
child_process.spawnSync("obsidian-export", ["./src", "./intermediate"]);

const files = fs.readdirSync("./intermediate");
 
while (files.length > 0) {
  const file = files.pop();
  if (file == null) {
    break;
  }
  const pathToFile = `./intermediate/${file}`;
  const fileStats = fs.lstatSync(pathToFile);
  // Recursively traverse the directory structure
  if (fileStats.isDirectory()) {
    fs.mkdirSync(`./site/${file}`, { recursive: true });
    const children = fs.readdirSync(pathToFile);
    files.push(...children.map((child) => `${file}/${child}`));
    continue;
  }

  const contents = fs.readFileSync(pathToFile, { encoding: "utf8" });
  // Strip secret notes
  const [censoredContents] = contents.split("---");
  // Remove incorrect file extensions from link targets
  const input = censoredContents.replace(/.md\)/g, ")").replace(/.md#/g, "#");
  const process = child_process.spawnSync(
    "pulldown-cmark",
    ["--enable-heading-attributes"],
    { input }
  );
  const [name] = file.split(".");
  const [firstLine] = contents.split("\n");
  const title = firstLine.startsWith("# ")
    ? `Codex: ${firstLine.substring(2)}`
    : "Armour Astir";

  const html = `<html><head><title>${title}</title><meta name="viewport" content="width=device-width, initial-scale=1" /><link rel="stylesheet" href="/style.css"></head><body><a href="/">To Index</a>${process.stdout.toString()}</body></html>`;
  // Add appropriate anchor IDs to link to the middle of documents
  const { document } = new jsdom.JSDOM(html).window;
  document.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach((node) => {
    const innerText = node.textContent ?? "";
    if (innerText) {
      node.id = innerText.toLowerCase().replace(/ /g, "-");
    }
  });
  fs.writeFileSync(`./site/${name}.html`, document.documentElement.innerHTML);
}

The Github action (no idea why this is running on macOS and not Linux?)

on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: macOS-latest
    steps:
      - uses: actions/checkout@master
      - name: Install obsidian-export
        uses: baptiste0928/cargo-install@v1
        with:
          crate: obsidian-export
      - name: Install pulldown-cmark
        uses: baptiste0928/cargo-install@v1
        with:
          crate: pulldown-cmark
      - uses: actions/setup-node@v3
        with:
          node-version: 16
          cache: 'npm'
      - name: Run obsidian-export
        run: mkdir ./intermediate && obsidian-export ./src ./intermediate
      - name: Build HTML files
        run: npm ci && npm run build
      - name: Push
        run: git checkout -b pub && git add . && git commit -am "Build" && git push -fu origin pub

fools-pyrite
@fools-pyrite

I can just do the same thing for my blog and write blog posts on Obsidian. Then sync those files out into Astro and generate my HTML. Why have I been writing blog posts in vim