standardSite

tcmts.content.standardSite · #kthz6sqo · function · runs anywhere

A blog (any site of posts) as a standard.site publication: a site.standard.publication record for it, and a site.standard.document for each post, its Markdown in it as at.markpub.markdown and as plain text. Their keys are TIDs, as these records' lexicons ask, made from what doesn't change (the publication's from its address, a post's from its day and its name), so writing them again (tcm publish) updates them, and a site's pages can name them before they're written.

const site = standardSite({
  did: "did:plc:vh4czvu5aijkaqge5huayq53",
  url: "https://tcm.codes/blog",
  name: "tcm blog",
  posts: [{ name: "hello", path: "/hello.html", title: "Hello", publishedAt: "2026-11-07", markdown: "Hi *there*." }],
});
site.documents[0]!.uri; // "at://did:plc:vh4czvu5aijkaqge5huayq53/site.standard.document/3mzop7dzob5dp"
site.wellKnown.path; // "/.well-known/site.standard.publication/blog"

✗ this example doesn't typecheck: Cannot find name 'standardSite'.

import { markdown } from "#codebase/tcmts/content";
import type { StandardPost, StandardRecord, StandardSite } from "#codebase/tcmts/content";

export function standardSite(site: {
  did: string;
  /** the publication's address: its posts' paths are under it */
  url: string;
  name: string;
  description?: string;
  posts: StandardPost[];
}): StandardSite {
  if (!/^did:[a-z]+:[A-Za-z0-9._:%-]+$/.test(site.did)) throw new Error(`${site.did} isn't a DID`);
  const at = new URL(site.url);
  if (at.protocol !== "https:" && at.protocol !== "http:")
    throw new Error(`${site.url}: a publication is at a web address`);
  const base = `${at.origin}${at.pathname.replace(/\/+$/, "")}`;
  const where = at.pathname.replace(/\/+$/, "");
  const graphemes = (s: string) => [...new Intl.Segmenter().segment(s)].length;
  const fits = (what: string, s: string, most: number) => {
    if (graphemes(s) > most)
      throw new Error(`${what} is ${graphemes(s)} characters: ${most} at most`);
    return s;
  };
  const moment = (d: string) =>
    new Date(/^\d{4}-\d{2}-\d{2}$/.test(d) ? `${d}T00:00:00Z` : d).toISOString();
  // a record's key: a TID (microseconds since the epoch, then a 10-bit clock id, in base32-sortable), made from what
  // doesn't change: the publication's from its address (a moment of 2025-01-01), a post's from its day and its name
  const hash = (s: string, seed: number) => {
    let h = seed >>> 0;
    for (const c of s) h = Math.imul(h ^ c.codePointAt(0)!, 16777619) >>> 0;
    return h;
  };
  const tid = (day: number, of: string) => {
    let n =
      ((BigInt(day) * 86_400_000_000n + BigInt(hash(of, 2166136261))) << 10n) |
      BigInt(hash(of, 40503) & 1023);
    let out = "";
    for (let i = 0; i < 13; i++, n >>= 5n)
      out = "234567abcdefghijklmnopqrstuvwxyz"[Number(n & 31n)]! + out;
    return out;
  };
  const dayOf = (d: string) => Math.floor(Date.parse(moment(d)) / 86_400_000);
  const own = tid(dayOf("2025-01-01"), base);
  const uri = (collection: string, rkey: string) => `at://${site.did}/${collection}/${rkey}`;
  const publication: StandardRecord = {
    collection: "site.standard.publication",
    rkey: own,
    uri: uri("site.standard.publication", own),
    record: {
      $type: "site.standard.publication",
      url: base,
      name: fits(`${site.url}'s name`, site.name, 500),
      ...(site.description
        ? { description: fits(`${site.url}'s description`, site.description, 3000) }
        : {}),
    },
  };
  // its Markdown as readers elsewhere take it: a `{@link}` as its name, in code; relative links in full
  const published = (md: string) =>
    md
      .replace(
        /\{@link(?:code|plain)?\s+([\w$.-]+)(?:\s*\|\s*|\s+)?([^}]*)\}/g,
        (_, name: string, label: string) =>
          `\`${label.trim() || name.slice(name.lastIndexOf(".") + 1)}\``,
      )
      .replace(
        /\]\((?!#|[a-z][a-z0-9+.-]*:|\/\/)([^)\s]+)/gi,
        (_, to: string) => `](${new URL(to, `${base}/`).href}`,
      );
  const plain = (md: string) =>
    markdown(md)
      .replace(/<[^>]*>/g, "")
      .replace(
        /&(lt|gt|quot|#39|amp);/g,
        (_, e: string) => ({ lt: "<", gt: ">", quot: '"', "#39": "'", amp: "&" })[e]!,
      )
      .replace(/\n{3,}/g, "\n\n")
      .trim();
  const names = new Set<string>();
  const documents = site.posts.map((p): StandardRecord => {
    if (names.has(p.name)) throw new Error(`two posts are named ${p.name}`);
    names.add(p.name);
    if (
      Number.isNaN(
        Date.parse(
          /^\d{4}-\d{2}-\d{2}$/.test(p.publishedAt) ? `${p.publishedAt}T00:00:00Z` : p.publishedAt,
        ),
      )
    )
      throw new Error(`${p.name}'s publishedAt isn't a date: ${p.publishedAt}`);
    const rkey = tid(dayOf(p.publishedAt), `${base} ${p.name}`);
    return {
      collection: "site.standard.document",
      rkey,
      uri: uri("site.standard.document", rkey),
      record: {
        $type: "site.standard.document",
        site: publication.uri,
        path: p.path.startsWith("/") ? p.path : `/${p.path}`,
        title: fits(`${p.name}'s title`, p.title, 500),
        publishedAt: moment(p.publishedAt),
        ...(p.updatedAt ? { updatedAt: moment(p.updatedAt) } : {}),
        ...(p.description
          ? { description: fits(`${p.name}'s description`, p.description, 3000) }
          : {}),
        ...(p.tags?.length
          ? { tags: p.tags.map((t) => fits(`${p.name}'s tag ${t}`, t, 128)) }
          : {}),
        ...(p.markdown !== undefined
          ? {
              textContent: plain(p.markdown),
              content: {
                $type: "at.markpub.markdown",
                text: { $type: "at.markpub.text", markdown: published(p.markdown) },
                flavor: "gfm",
                renderingRules: "marked",
              },
            }
          : {}),
      },
    };
  });
  const byName = new Map(site.posts.map((p, i) => [p.name, documents[i]!]));
  return {
    did: site.did,
    publication,
    documents,
    wellKnown: { path: `/.well-known/site.standard.publication${where}`, text: publication.uri },
    link(name) {
      const d = byName.get(name);
      if (!d) throw new Error(`there's no post named ${name}`);
      return `<link rel="site.standard.document" href="${d.uri}">`;
    },
  };
}

uses

used by