From 544a9f36634b772f5f3ec1dcda8b2161ab70e9af Mon Sep 17 00:00:00 2001 From: Theis Pieter Hollebeek Date: Mon, 13 Oct 2025 13:23:05 +0200 Subject: [PATCH] statics, table of contents --- docs/build.ts | 70 +++++++++++++++++++++++++++++++ docs/deno.jsonc | 3 ++ docs/render.ts | 86 --------------------------------------- docs/src/gamelib.md | 8 +++- docs/static/header_ids.js | 61 +++++++++++++++++++++++++++ 5 files changed, 140 insertions(+), 88 deletions(-) create mode 100644 docs/build.ts delete mode 100644 docs/render.ts create mode 100644 docs/static/header_ids.js diff --git a/docs/build.ts b/docs/build.ts new file mode 100644 index 0000000..acfb7d1 --- /dev/null +++ b/docs/build.ts @@ -0,0 +1,70 @@ +import { Renderer } from "@libs/markdown"; +import HighlightPlugin from "@libs/markdown/plugins/highlighting"; +import { walk } from "@std/fs"; +import * as pathTools from "@std/path"; + +function injectIntoTemplate(name: string, rendered: string): string { + let content = [ + "", + "", + "", + [ + `${name}`, + '', + '', + ], + "", + "", + [ + rendered, + ], + "", + "", + ]; + while (content.some((x) => Array.isArray(x))) { + content = content.flat(); + } + return content.join(""); +} + +async function renderMarkdown() { + const renderer = await Renderer.with({ + plugins: [HighlightPlugin], + }); + for await ( + const entry of walk("src", { exts: [".md"], includeDirs: false }) + ) { + const parsed = pathTools.parse(entry.path); + parsed.dir = parsed.dir.replace(/^src[\\/]?/, ""); + parsed.dir = pathTools.join("-", parsed.dir); + parsed.ext = ".html"; + parsed.base = `${parsed.name}${parsed.ext}`; + + await Deno.mkdir(parsed.dir, { recursive: true }); + const content = await renderer.render(await Deno.readTextFile(entry.path)); + await Deno.writeTextFile( + pathTools.format(parsed), + injectIntoTemplate(parsed.name, content), + ); + } +} + +async function copyStaticFiles() { + for await (const entry of walk("static", { includeDirs: false })) { + const parsed = pathTools.parse(entry.path); + parsed.dir = parsed.dir.replace(/^static[\\/]?/, ""); + parsed.dir = pathTools.join("-", parsed.dir); + + await Deno.mkdir(parsed.dir, { recursive: true }); + await Deno.copyFile(entry.path, pathTools.format(parsed)); + } +} + +async function main() { + await renderMarkdown(); + await copyStaticFiles(); +} + +if (import.meta.main) { + main(); +} diff --git a/docs/deno.jsonc b/docs/deno.jsonc index 07a5bdc..4192d83 100644 --- a/docs/deno.jsonc +++ b/docs/deno.jsonc @@ -7,5 +7,8 @@ "@libs/markdown": "jsr:@libs/markdown@^2.0.4", "@std/fs": "jsr:@std/fs@^1.0.19", "@std/path": "jsr:@std/path@^1.1.2" + }, + "tasks": { + "build": "deno run -A build.ts" } } diff --git a/docs/render.ts b/docs/render.ts deleted file mode 100644 index e208212..0000000 --- a/docs/render.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Renderer } from "@libs/markdown"; -import HighlightPlugin from "@libs/markdown/plugins/highlighting"; -import { walk } from "@std/fs"; -import * as pathTools from "@std/path"; - -function injectIntoTemplate(name: string, rendered: string): string { - let content = [ - "", - "", - "", - [ - `${name}`, - ], - "", - "", - [ - rendered, - "", - ], - "", - "", - ]; - while (content.some((x) => Array.isArray(x))) { - content = content.flat(); - } - return content.join(""); -} - -async function main() { - const renderer = await Renderer.with({ - plugins: [HighlightPlugin], - }); - for await ( - const entry of walk("src", { - exts: [".md"], - }) - ) { - const parsed = pathTools.parse(entry.path); - parsed.dir = parsed.dir.replace(/^src[\\/]?/, ""); - parsed.dir = pathTools.join("-", parsed.dir); - parsed.ext = ".html"; - parsed.base = `${parsed.name}${parsed.ext}`; - - await Deno.mkdir(parsed.dir, { recursive: true }); - const content = await renderer.render(await Deno.readTextFile(entry.path)); - await Deno.writeTextFile( - pathTools.format(parsed), - injectIntoTemplate(parsed.name, content), - ); - } -} - -if (import.meta.main) { - main(); -} diff --git a/docs/src/gamelib.md b/docs/src/gamelib.md index de0c55a..efba5af 100644 --- a/docs/src/gamelib.md +++ b/docs/src/gamelib.md @@ -1,5 +1,9 @@ # Gamelib +## Contents + + + ## Models ### `Color` @@ -22,8 +26,8 @@ lib.drawRect(100, 0, 100, 100, lib.rgb(192, 127, 172)); A type of string. -Represents JavaScript's `KeyboardEvent.key` -([link](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key)) property. +Represents JavaScript's +[`KeyboardEvent.key`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) property. Example: diff --git a/docs/static/header_ids.js b/docs/static/header_ids.js new file mode 100644 index 0000000..8e4e0f4 --- /dev/null +++ b/docs/static/header_ids.js @@ -0,0 +1,61 @@ +function renderTableOfContents() { + const root = document.querySelector("table-of-contents"); + + const list = document.createElement("ul"); + + const headers = document.querySelectorAll("h2,h3,h4,h5,h6"); + + const ancestors = []; + for (const header of headers) { + const depth = parseInt(header.tagName.slice(1)) - 1; + while (ancestors.length >= depth) { + ancestors.pop(); + } + const li = document.createElement("li"); + const a = document.createElement("a"); + a.textContent = header.textContent; + a.href = `#${header.id}`; + const ul = document.createElement("ul"); + li.replaceChildren(a, ul); + const mostRecent = ancestors[ancestors.length - 1]; + if (mostRecent === undefined) { + list.appendChild(li); + } else { + mostRecent.appendChild(li); + } + ancestors.push(ul); + } + + root.replaceChildren(list); +} + +function slugify(elements) { + console.log(elements); + return elements + .map((element, i) => { + if (i === 0) return null; + const content = element.textContent.trim(); + if (content.startsWith("lib.")) { + const [name] = content.match(/^lib\.[^\(]+/); + return name.trim(); + } + return content; + }) + .filter((x) => x !== null) + .join("-"); +} +function attachIdToHeaders() { + const headers = document.querySelectorAll("h1,h2,h3,h4,h5,h6"); + const ancestors = []; + for (const header of headers) { + const depth = parseInt(header.tagName.slice(1)); + while (ancestors.length >= depth) { + ancestors.pop(); + } + ancestors.push(header); + if (depth > 1) header.id = slugify(ancestors); + } +} + +attachIdToHeaders(); +renderTableOfContents();