asw-v01: archive deferred content (packs, site, lab, legacy examples)

- 2.1: packs/ -> archive/packs/
- 2.2: site/ -> archive/site/
- 2.3: src/lab/ -> archive/lab/
- 2.4: examples/ -> archive/examples-legacy/ (SSI-based)
This commit is contained in:
exe.dev user 2026-06-07 10:39:21 +02:00
parent 416fe2f180
commit e47a9f4401
173 changed files with 11 additions and 5 deletions

View file

@ -0,0 +1,105 @@
---
title: "ASW Pandoc Pack"
description: "Convert markdown to ASW-styled HTML with one command"
layout: prose
---
# ASW Pandoc Pack
Converts GFM markdown to fully ASW-styled HTML. Write markdown natively; the pack renders it with correct `data-attribute` semantics.
## Usage
```bash
pandoc input.md \
--from gfm \
--lua-filter packs/pandoc/asw.lua \
--template packs/pandoc/asw.html5 \
-o output.html
```
## What it does
### Semantic mapping (asw.lua)
| Markdown | Output HTML |
|---|---|
| `- [ ] 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.
Wikilinks: punctuation attached to `]]` is preserved outside the link element. Unresolved link detection is not automatic — the href slug is always generated; resolution is a build-time concern.
### Frontmatter → data-attributes (asw.html5)
YAML frontmatter keys map to page-level ASW properties:
```yaml
---
title: "Session Report — 2026-04-02"
description: "Summary of what happened"
layout: prose # → data-layout on <main> (default: prose)
status: done # → data-status on <main> and in header badge
date: 2026-04-02 # → <time datetime="...">
section: "Sessions" # → <p data-text="eyebrow"> above <h1>
tags:
- session
- autonomous
# Session metadata (if agent-authored):
agent: vigilio
model: claude-sonnet-4-6
mode: autonomous # → <span data-mode="autonomous">
session: 10
---
```
Keys not set are simply omitted — no empty elements in the output.
## Layout values
The `layout` key maps directly to `data-layout` on `<main>`:
| Value | Use case |
|---|---|
| `prose` (default) | Articles, notes, documentation |
| `docs` | Two-column docs layout |
| `fluid` | Full-width, no max-width |
Any `data-layout` value supported by `asw.css` works here.
## Status values
| Value | Meaning |
|---|---|
| `done` | Complete |
| `awake` | Active agent/session |
| `sleeping` | Inactive |
| `blocked` | Waiting on dependency |
## CSS dependency
The pack generates HTML that requires `asw.css` for styling. The template links `/asw.css` by default. Override with `--variable css=/path/to/asw.css`.
## Relationship to the build pipeline
`build.sh` uses this pack (via the `doc.html` template) for `content/``docs/` compilation. The standalone pack is also useful for:
- Rendering vault notes as public pages
- One-off markdown → ASW HTML conversion
- Integration into other build systems (trentuna-web, agent pipelines)
## Files
```
packs/pandoc/
├── asw.html5 pandoc HTML5 template — page structure, frontmatter vars
├── asw.lua Lua filter — task lists, callouts, wikilinks
└── README.md this file
```

View file

@ -0,0 +1,67 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>$if(title)$$title$$else$Untitled$endif$</title>
$if(description)$ <meta name="description" content="$description$">
$endif$
$-- CSS: link to asw.css (adjust path for your deployment) $
<link rel="stylesheet" href="/asw.css">
$for(css)$ <link rel="stylesheet" href="$css$">
$endfor$
$if(header-includes)$$header-includes$$endif$
</head>
<body>
$-- Page header: title + optional eyebrow / metadata $
$if(title)$
<header>
<hgroup>
$if(section)$ <p data-text="eyebrow">$section$</p>
$endif$ <h1>$title$</h1>
$if(description)$ <p data-text="lead">$description$</p>
$endif$ </hgroup>
$-- Session metadata block (agent-authored content) $
$if(agent)$
<div data-session>
<span data-session-meta>
$if(date)$ <time datetime="$date$">$date$</time>$endif$
$if(agent)$ <span>$agent$</span>$endif$
$if(model)$ <span>$model$</span>$endif$
$if(mode)$ <span data-mode="$mode$">$mode$</span>$endif$
$if(session)$ <span>session $session$</span>$endif$
</span>
$if(status)$ <span data-status="$status$">$status$</span>$endif$
</div>
$endif$
$-- Tags $
$if(tags)$
<nav aria-label="tags">
$for(tags)$ <a data-tag href="/tags/$tags$">$tags$</a>
$endfor$ </nav>
$endif$
</header>
$endif$
$-- Main content — layout from frontmatter or default to prose $
<main$if(layout)$ data-layout="$layout$"$else$ data-layout="prose"$endif$$if(status)$ data-status="$status$"$endif$>
$body$
</main>
$-- Footer $
$if(date)$
<footer>
<small>
$if(date)$ <time datetime="$date$">$date$</time>$endif$
$if(author)$ · $for(author)$$author$$sep$, $endfor$$endif$
</small>
</footer>
$endif$
$if(include-after)$$include-after$$endif$
</body>
</html>

View file

@ -0,0 +1,272 @@
-- asw.lua — Pandoc Lua filter for Agentic Semantic Web (ASW)
-- Converts GFM markdown constructs to ASW data-attribute HTML
--
-- Usage:
-- pandoc input.md --from gfm --lua-filter asw.lua --template asw.html5 -o output.html
--
-- Transforms:
-- - [ ] item → <li data-task="todo">
-- - [x] item → <li data-task="done">
-- > [!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>
-- ── Callouts ─────────────────────────────────────────────────────────────────
-- GitHub callout syntax: > [!TYPE]\n> content → <div data-callout="type">
local CALLOUT_MAP = {
NOTE = "note",
INFO = "note",
IMPORTANT = "note",
WARNING = "warning",
CAUTION = "warning",
TIP = "tip",
ERROR = "error",
DANGER = "error",
}
local CALLOUT_LABEL = {
note = "Note",
warning = "Warning",
tip = "Tip",
error = "Error",
}
function BlockQuote(el)
local first = el.content[1]
if not first or (first.t ~= "Para" and first.t ~= "Plain") then return el end
-- The first inline should be a Str like "[!NOTE]"
local first_inline = first.content and first.content[1]
if not first_inline or first_inline.t ~= "Str" then return el end
local marker = first_inline.text:match("^%[!(%u+)%]$")
if not marker then return el end
local callout_type = CALLOUT_MAP[marker]
if not callout_type then return el end
local label = CALLOUT_LABEL[callout_type] or marker:sub(1,1) .. marker:sub(2):lower()
local blocks = {
pandoc.RawBlock("html", '<div data-callout="' .. callout_type .. '">'),
pandoc.RawBlock("html", '<p data-callout-title>' .. label .. '</p>'),
}
-- First para: strip the [!MARKER] token and optional following SoftBreak/Space
local inlines = first.content
local start_i = 2
if inlines[start_i] and
(inlines[start_i].t == "SoftBreak" or inlines[start_i].t == "Space") then
start_i = start_i + 1
end
local rest_inlines = {}
for i = start_i, #inlines do
table.insert(rest_inlines, inlines[i])
end
if #rest_inlines > 0 then
table.insert(blocks, pandoc.Para(rest_inlines))
end
-- Remaining blocks in the blockquote
for i = 2, #el.content do
table.insert(blocks, el.content[i])
end
table.insert(blocks, pandoc.RawBlock("html", '</div>'))
return blocks
end
-- ── Task Lists ───────────────────────────────────────────────────────────────
-- GFM: - [ ] → <li data-task="todo">, - [x] → <li data-task="done">
-- Pandoc (GFM mode) emits checkboxes as RawInline html: <input type="checkbox" ...>
-- Pandoc 3.x encodes GFM task list checkboxes as Unicode Str:
-- ☒ (U+2612) = checked/done, ☐ (U+2610) = unchecked/todo
local CHECKBOX_DONE = "\xe2\x98\x92" -- ☒ UTF-8
local CHECKBOX_TODO = "\xe2\x98\x90" -- ☐ UTF-8
local function checkbox_state(inline)
if inline and inline.t == "Str" then
if inline.text == CHECKBOX_DONE then return "done" end
if inline.text == CHECKBOX_TODO then return "todo" end
end
return nil
end
function BulletList(el)
-- First pass: check if any item is a task
local has_tasks = false
for _, item in ipairs(el.content) do
local first = item[1]
if first and (first.t == "Plain" or first.t == "Para") and first.content[1] then
if checkbox_state(first.content[1]) then
has_tasks = true
break
end
end
end
if not has_tasks then return el end
-- Rebuild as explicit HTML with data-task attributes
local parts = { pandoc.RawBlock("html", "<ul>") }
for _, item in ipairs(el.content) do
local first = item[1]
local state = nil
if first and (first.t == "Plain" or first.t == "Para") and first.content[1] then
state = checkbox_state(first.content[1])
end
if state then
table.insert(parts, pandoc.RawBlock("html", '<li data-task="' .. state .. '">'))
-- Strip checkbox inline (index 1) and optional space (index 2)
local trimmed = {}
for i, inline in ipairs(first.content) do
if i == 1 then
-- skip checkbox
elseif i == 2 and inline.t == "Space" then
-- skip leading space after checkbox
else
table.insert(trimmed, inline)
end
end
if #trimmed > 0 then
table.insert(parts, pandoc.Plain(trimmed))
end
-- Remaining blocks in this item
for i = 2, #item do
table.insert(parts, item[i])
end
table.insert(parts, pandoc.RawBlock("html", "</li>"))
else
-- Regular list item — emit verbatim
table.insert(parts, pandoc.RawBlock("html", "<li>"))
for _, block in ipairs(item) do
table.insert(parts, block)
end
table.insert(parts, pandoc.RawBlock("html", "</li>"))
end
end
table.insert(parts, pandoc.RawBlock("html", "</ul>"))
return parts
end
-- ── Wikilinks ─────────────────────────────────────────────────────────────────
-- [[target|label]] or [[target]] → <a data-wikilink href="#slug">label</a>
--
-- Pandoc 3.x tokenizes at whitespace, so [[target|label with spaces]] arrives as
-- multiple Str/Space tokens. process_wikilinks coalesces adjacent Str+Space runs
-- into a combined string before scanning for [[...]] patterns, then reconstructs
-- the inline list. Non-Str/Space inlines (Bold, Emph, Code, etc.) pass through.
local function slugify(text)
return text:lower():gsub("[%s_]+", "-"):gsub("[^%w%-]", "")
end
-- Scan combined for [[...]] patterns and emit inlines.
-- Returns a list of inlines with wikilinks replaced, plus a changed flag.
local function scan_for_wikilinks(combined)
local parts = {}
local pos = 1
local changed = false
while pos <= #combined do
local s, e = combined:find("%[%[", pos)
if not s then
if pos <= #combined then
table.insert(parts, pandoc.Str(combined:sub(pos)))
end
break
end
if s > pos then
table.insert(parts, pandoc.Str(combined:sub(pos, s - 1)))
end
local close_s, close_e = combined:find("%]%]", e + 1)
if not close_s then
table.insert(parts, pandoc.Str("[["))
pos = e + 1
else
local inner = combined:sub(e + 1, close_s - 1)
local target, label = inner:match("^([^|]+)|(.+)$")
if not target then
target = inner
label = inner
end
target = target:match("^%s*(.-)%s*$")
label = label:match("^%s*(.-)%s*$")
table.insert(parts, pandoc.RawInline("html",
'<a data-wikilink href="#' .. slugify(target) .. '">' .. label .. '</a>'))
pos = close_e + 1
changed = true
end
end
return parts, changed
end
local function process_wikilinks(inlines)
-- Pass 1: coalesce runs of Str+Space into combined strings, scan for wikilinks.
-- Non-text inlines (Emph, Strong, Code, RawInline, etc.) flush any pending run first.
local result = {}
local changed = false
local i = 1
while i <= #inlines do
local el = inlines[i]
if el.t == "Str" or el.t == "Space" then
-- Collect a contiguous Str+Space run
local run = {}
local combined = ""
while i <= #inlines and (inlines[i].t == "Str" or inlines[i].t == "Space") do
if inlines[i].t == "Str" then
combined = combined .. inlines[i].text
else
combined = combined .. " "
end
table.insert(run, inlines[i])
i = i + 1
end
if combined:find("%[%[") then
local parts, any_changed = scan_for_wikilinks(combined)
if any_changed then
for _, part in ipairs(parts) do table.insert(result, part) end
changed = true
else
-- No wikilinks resolved — emit original tokens unchanged
for _, tok in ipairs(run) do table.insert(result, tok) end
end
else
-- No [[ at all — emit original tokens unchanged
for _, tok in ipairs(run) do table.insert(result, tok) end
end
else
table.insert(result, el)
i = i + 1
end
end
return changed and result or nil
end
function Para(el)
local r = process_wikilinks(el.content)
if r then return pandoc.Para(r) end
end
function Plain(el)
local r = process_wikilinks(el.content)
if r then return pandoc.Plain(r) end
end
function Header(el)
local r = process_wikilinks(el.content)
if r then return pandoc.Header(el.level, r, el.attr) end
end

View file

@ -0,0 +1,50 @@
<!doctype html>
<html lang="en">
<head>
<!--#include virtual="/_include/head.html" -->
<title>$title$ — ASW Docs</title>
$if(description)$ <meta name="description" content="$description$">
$endif$</head>
<body>
<!--#include virtual="/_include/nav.html" -->
<div data-layout="docs">
<!--#include virtual="/_include/sidebar.html" -->
<article>
<h1>$title$</h1>
$if(description)$ <p data-text="lead">$description$</p>
$endif$
$body$
$if(prev-url)$
<nav data-role="prev-next">
$if(prev-url)$ <a href="$prev-url$" rel="prev">
<small>← Previous</small>
<span>$prev-title$</span>
</a>
$endif$
$if(next-url)$ <a href="$next-url$" rel="next">
<small>Next →</small>
<span>$next-title$</span>
</a>
$endif$
</nav>
$endif$
</article>
<aside data-toc>
<nav aria-label="On this page" data-nav="toc">
<small>On this page</small>
<ul></ul>
</nav>
</aside>
</div>
<!--#include virtual="/_include/footer.html" -->
<script src="/docs/toc-spy.js"></script>
</body>
</html>

View file

@ -0,0 +1,22 @@
<!doctype html>
<html lang="en">
<head>
<!--#include virtual="/_include/head.html" -->
<title>$title$ — ASW Examples</title>
$if(description)$ <meta name="description" content="$description$">
$endif$</head>
<body>
<!--#include virtual="/_include/nav.html" -->
<main>
<header>
<h1>$title$</h1>
$if(description)$ <p data-text="lead">$description$</p>
$endif$ </header>
$body$
</main>
<!--#include virtual="/_include/footer.html" -->
</body>
</html>

View file

@ -0,0 +1,20 @@
<!doctype html>
<html lang="en">
<head>
<!--#include virtual="/_include/head.html" -->
<title>$title$ — ASW</title>
$if(description)$ <meta name="description" content="$description$">
$endif$</head>
<body>
<!--#include virtual="/_include/nav.html" -->
<main data-layout="prose">
<h1>$title$</h1>
$if(description)$ <p data-text="lead">$description$</p>
$endif$
$body$
</main>
<!--#include virtual="/_include/footer.html" -->
</body>
</html>

View file

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<!--#include virtual="/_include/head.html" -->
<title>$title$ — ASW</title>
$if(description)$ <meta name="description" content="$description$">
$endif$</head>
<body>
<!--#include virtual="/_include/nav.html" -->
$body$
<!--#include virtual="/_include/footer.html" -->
</body>
</html>