Something went wrong. Try again.
Identities for entities did.bot
agent llm did
Something went wrong. Try again.
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127#!/usr/bin/env node// Copies the repo's own docs/*.md into src/content/docs/ so Astro's content// collection can read them, and rewrites the relative links inside them so// they resolve on the published site instead of on a GitHub-style tree.//// The docs live at the repo root, not inside site/, because they are real,// human-written documentation shared with `cargo doc` (see// crates/didbot/src/lib.rs, which include_str!s the same files into the// crate's rustdoc). This script does not fork them: it reads them where they// live and writes a generated copy, which is why src/content/docs/ is// gitignored — regenerate it, never hand-edit it.//// Link rewriting:// - A link to another page under docs/ (e.g. "trust-model.md" or// "../docs/trust-model.md") becomes "/docs/<slug>/", the route the docs// collection renders that page at.// - An in-page anchor ("#section") is left alone.// - Anything absolute (http/https/mailto) is left alone.// - Any other relative link (e.g. "../README.md",// "../crates/didbot-stack/README.md") points at a file this site does not// publish, so it is rewritten to that file's location in the source// repository on Tangled, where it always resolves.import { createHash } from "node:crypto";import { execFileSync } from "node:child_process";import { mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";import { dirname, join, resolve } from "node:path";import { fileURLToPath } from "node:url";
const here = dirname(fileURLToPath(import.meta.url));const siteRoot = resolve(here, "..");const repoRoot = resolve(siteRoot, "..");const docsSrc = join(repoRoot, "docs");const docsDest = join(siteRoot, "src", "content", "docs");
// The canonical place to browse a file that this site does not render.const SOURCE_REPO = "https://tangled.org/permadeath.com/didbot/blob/main";
const LINK_RE = /\]\(([^)]+)\)/g;// Reference-style link definitions: "[label]: target" on its own line. Used// in docs/conformance.md for rustdoc intra-doc links like// "[`AgentDid`]: crate::identity::AgentDid" — a shorthand markdown-it expands// with no parentheses in sight, so the inline-link regex above never sees it.const REF_LINK_RE = /^(\[[^\]]+\]:\s*)(\S+)/gm;// A rustdoc intra-doc link: a bare Rust item path, not a URL and not a// filesystem path. It only resolves inside rustdoc itself, so on this site it// becomes a link into the /api/ mount's search rather than a dead link.const RUST_PATH_RE = /^crate::[\w:]+$/;
function titleFor(markdown, fallback) { const match = markdown.match(/^#\s+(.+)$/m); return match ? match[1].trim() : fallback;}
function rewriteLink(target, docFile) { if (/^(https?:)?\/\//.test(target) || target.startsWith("mailto:") || target.startsWith("#")) { return target; }
if (RUST_PATH_RE.test(target)) { const lastSegment = target.split("::").pop(); return `/api/didbot/?search=${encodeURIComponent(lastSegment)}`; }
const [pathPart, anchor] = target.split("#"); const anchorSuffix = anchor ? `#${anchor}` : "";
if (pathPart === "") { return target; }
// Resolve relative to the *source* file's real location, not the copy. const resolved = resolve(dirname(join(docsSrc, docFile)), pathPart);
if (resolved.startsWith(docsSrc) && resolved.endsWith(".md")) { const slug = resolved.slice(docsSrc.length + 1).replace(/\.md$/, ""); return `/docs/${slug}/${anchorSuffix}`; }
if (resolved.startsWith(repoRoot)) { const repoRelative = resolved.slice(repoRoot.length + 1); return `${SOURCE_REPO}/${repoRelative}${anchorSuffix}`; }
// Outside the repo entirely — nothing sensible to rewrite it to. return target;}
rmSync(docsDest, { recursive: true, force: true });mkdirSync(docsDest, { recursive: true });
const files = readdirSync(docsSrc).filter((name) => name.endsWith(".md"));if (files.length === 0) { throw new Error(`no markdown files found in ${docsSrc}`);}
// Real provenance, not decoration: a content hash of the actual file this// page renders, and the actual commit that last touched it — the site's// "a record is a signed commit" argument, made touchable rather than stated.// Falls back to "unknown" rather than a fake hash if git is unavailable// (a tarball checkout with no `.git`, say); never invents one.function lastCommit(file) { try { return execFileSync( "git", ["log", "-1", "--format=%h", "--", `docs/${file}`], { cwd: repoRoot, encoding: "utf8" }, ).trim() || "unknown"; } catch { return "unknown"; }}
for (const file of files) { const raw = readFileSync(join(docsSrc, file), "utf8"); const rewritten = raw .replace(LINK_RE, (whole, target) => `](${rewriteLink(target, file)})`) .replace(REF_LINK_RE, (whole, prefix, target) => `${prefix}${rewriteLink(target, file)}`); const contentHash = createHash("sha256").update(raw).digest("hex").slice(0, 12); const commit = lastCommit(file); const slug = file.replace(/\.md$/, ""); const title = titleFor(raw, slug); const frontmatter = `---\ntitle: ${JSON.stringify(title)}\nslug: ${JSON.stringify(slug)}\nsourcePath: ${JSON.stringify(`docs/${file}`)}\ncontentHash: ${JSON.stringify(contentHash)}\nlastCommit: ${JSON.stringify(commit)}\n---\n\n`; writeFileSync(join(docsDest, file), frontmatter + rewritten);}
console.log(`prepare-docs: wrote ${files.length} page(s) to ${docsDest}`);