fools-pyrite

computer toucher; RPG enjoyer


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


You must log in to comment.