feat(notes): render macroplan code blocks as a delivery plan grid
All checks were successful
CI / verify (push) Successful in 2m9s

Follows the tikz pattern: the fence emits a base64 placeholder, then
the post-render hook lazily imports the parser and grid (separate
chunks) and mounts the grid only when a placeholder exists. Mono font
forced on the block because the flag-stacking math assumes Fira Code.
This commit is contained in:
Julien Calixte
2026-07-08 00:01:21 +02:00
parent 70f9a6b718
commit 1b6c7542d7
9 changed files with 154 additions and 6 deletions

View File

@@ -0,0 +1,40 @@
import { describe, expect, it } from "vitest"
import { encodeUTF8ToBase64 } from "@/utils/decodeBase64ToUTF8"
import { runMacroplan } from "./runMacroplan"
const placeholder = (source: string): HTMLElement => {
const el = document.createElement("div")
el.className = "macroplan-block"
el.dataset.macroplanSource = encodeUTF8ToBase64(source)
document.body.appendChild(el)
return el
}
describe("runMacroplan", () => {
it("mounts the grid onto a valid placeholder", async () => {
const el = placeholder(
'title = "Plan"\n\n[[feature]]\nname = "Auth"\nstart = 2026-06-01\noriginal = 2026-06-15\n'
)
await runMacroplan(".macroplan-block")
expect(el.dataset.macroplanRendered).toBe("true")
expect(el.querySelector(".macroplan")).not.toBeNull()
expect(el.textContent).toContain("Auth")
el.remove()
})
it("renders the parse error inline for malformed sources", async () => {
const el = placeholder('[[feature]]\nname = "No dates"')
await runMacroplan(".macroplan-block")
expect(el.dataset.macroplanRendered).toBe("error")
expect(el.querySelector(".macroplan-error")?.textContent).toContain(
"missing `start`"
)
el.remove()
})
})

View File

@@ -0,0 +1,55 @@
import { createApp } from "vue"
import { decodeBase64ToUTF8 } from "@/utils/decodeBase64ToUTF8"
const renderMacroplanError = (el: HTMLElement, err: unknown): void => {
const msg = err instanceof Error ? err.message : String(err)
el.textContent = ""
const box = document.createElement("div")
box.className = "macroplan-error"
const title = document.createElement("strong")
title.textContent = "Macroplan error"
const detail = document.createElement("pre")
detail.textContent = msg
box.append(title, detail)
el.appendChild(box)
}
/**
* Mount a MacroplanGrid onto every ```macroplan placeholder in scope.
* The parser (smol-toml + valibot) and the grid component only load
* when a placeholder actually exists, so notes without a plan pay nothing.
*/
export const runMacroplan = async (querySelector: string): Promise<void> => {
const elements = Array.from(
document.querySelectorAll<HTMLElement>(querySelector)
).filter((el) => !el.dataset.macroplanRendered)
if (elements.length === 0) return
const [{ parseMacroplan }, { buildPlan }, { default: MacroplanGrid }] =
await Promise.all([
import("./model/parse"),
import("./model/plan"),
import("./components/MacroplanGrid.vue")
])
for (const el of elements) {
el.dataset.macroplanRendered = "pending"
const encoded = el.dataset.macroplanSource
if (!encoded) {
el.dataset.macroplanRendered = "error"
continue
}
try {
const plan = buildPlan(parseMacroplan(decodeBase64ToUTF8(encoded)))
el.textContent = ""
createApp(MacroplanGrid, { plan }).mount(el)
el.dataset.macroplanRendered = "true"
} catch (err) {
renderMacroplanError(el, err)
el.dataset.macroplanRendered = "error"
}
}
}