Pandoc Pack
Convert Markdown to ASW-styled HTML — task lists, callouts, and wikilinks become data-attributes automatically.
The site-builder story
ASW is not just a CSS file you link. It is a complete pipeline: an agent writes Markdown, the pandoc pack converts it to HTML, and the output is a fully styled page using ASW semantics — with zero classes required, zero manual HTML authoring.
content/note.md ──(pandoc + asw.lua + asw.html5)──▶ docs/note.html
The pack is what makes the vault a CMS. Write in Obsidian, publish
with ./build.sh site.
Semantic mapping
The Lua filter converts GFM Markdown constructs to ASW data-attribute HTML:
| Markdown | ASW output |
|---|---|
- [ ] task |
<li data-task="todo">task</li> |
- [x] done |
<li data-task="done">done</li> |
> [!NOTE] |
<div data-callout="note"> |
> [!WARNING] |
<div data-callout="warning"> |
> [!TIP] |
<div data-callout="tip"> |
> [!ERROR] |
<div data-callout="error"> |
[[target]] |
<a data-wikilink href="#target">target</a> |
[[target|label]] |
<a data-wikilink href="#target">label</a> |
Callout aliases: [!CAUTION] → warning,
[!IMPORTANT] / [!INFO] → note,
[!DANGER] → error.
Task lists
- [x] Build the CSS framework
- [x] Wire pandoc pack into build.sh
- [ ] Write the docs
- [ ] Publish to npm- Build the CSS framework
- Wire pandoc pack into build.sh
- Write the docs
- Publish to npm
Callouts
> [!NOTE]
> The pack requires pandoc 3.x. Earlier versions may handle GFM differently.
> [!WARNING]
> Wikilinks generate `href="#slug"` anchors. Link resolution is a build-time concern — the pack does not validate whether the target exists.Note
The pack requires pandoc 3.x. Earlier versions may handle GFM differently.
Warning
Wikilinks generate href="#slug" anchors. Link resolution
is a build-time concern — the pack does not validate whether the target
exists.
Wikilinks
See [[philosophy]] for why ASW chose this approach.
The [[pandoc pack|pack]] converts vault notes to web pages.See philosophy for why ASW chose this approach. The pack converts vault notes to web pages.
Frontmatter → page metadata
YAML frontmatter maps to page-level properties via the
asw.html5 template:
---
title: "Session Report — 2026-04-02"
description: "Summary of what happened"
layout: prose # → data-layout on <main> (default: prose)
status: done # → data-status badge in header
date: 2026-04-02 # → <time datetime="...">
section: "Sessions" # → eyebrow text above <h1>
tags:
- session
- autonomous
# Agent authorship (optional):
agent: vigilio
model: claude-sonnet-4-6
mode: autonomous # → <span data-mode="autonomous">
session: 10
---Unset keys produce no output — no empty elements in the rendered HTML.
Command-line usage
Standalone, without build.sh:
pandoc input.md \
--from gfm+yaml_metadata_block \
--lua-filter packs/pandoc/asw.lua \
--template packs/pandoc/asw.html5 \
--to html5 \
-o output.htmlThe +yaml_metadata_block extension enables YAML
frontmatter parsing.
With build.sh
build.sh site processes
content/docs/**/*.md and
content/examples/**/*.md automatically. The template is
selected from the frontmatter template: field (default:
page).
./build.sh site # compile all content/ → docs/
./build.sh all # CSS + site in one pass
./build.sh watch # rebuild on file change (requires inotify-tools)Source lives in content/. Built output lands in
docs/. Never edit docs/*.html directly — edits
will be overwritten on the next build.
Files
packs/pandoc/
├── asw.lua Lua filter — task lists, callouts, wikilinks
├── asw.html5 Pandoc HTML5 template — page structure, frontmatter vars
└── README.md Reference documentation
The vault-as-CMS model
The pandoc pack is what enables the vault-as-CMS workflow:
- Agent writes a note in
~/.napkin/knowledge/— standard Markdown with wikilinks, tasks, callouts - The note is synced or copied to
content/docs/ build.sh siteconverts it to a styled HTML page- nginx serves it from
docs/
No CMS. No database. No admin interface. The vault IS the content management system. The pack is the bridge between how agents write and how the web renders.
Tip
The pandoc pack is what makes the zero-class rule achievable at the
writing level. An agent writing Markdown never needs to think about
data-task, data-callout, or
data-wikilink. It writes naturally; the pack handles the
translation.