README
content
Content collections for a tcm codebase, as a library: a namespace of pages read as typed entries, each one's
frontmatter checked against a schema. tcm ships it, so tcm lib add tcm content adds the release your tcm has, with
no network (and tcm lib upgrade content the one a newer tcm has). It's a tcm library, not an npm package: it holds
everything its code uses but the yaml, marked and shiki packages.
import * as files from "#codebase/blog/posts";
import { collection, markdown } from "#codebase/app/lib/content";
import { z } from "zod";
export const posts = collection(files, {
schema: z.object({ title: z.string(), date: z.iso.date() }),
sort: (a, b) => b.data.date.localeCompare(a.data.date),
});
export const page = (name: string) => {
const post = posts.get(name);
return post && `<h1>${post.data.title}</h1>${markdown(post.body)}`;
};
What it has
- Collections:
collection(files, { schema, format?, sort? })reads a namespace of files (imported whole) as entries, each with itsname, itsdataas the schema makes it, and itsbody.all(),get(name)andcheck(name, text)read them; an entry that doesn't fit is named when it's read. - Any Standard Schema: Zod, Valibot, ArkType, or anything with a
~standardproperty. - Frontmatter:
frontmatter(text), a Markdown file's YAML at its top, and the text under it. JSON and YAML files are read whole (format). - Markdown:
markdown(text, { link?, highlight? }), as HTML;{@link name}shows the name, linked wherelinksays, and a fenced code block is ashighlightmakes it.await shiki({ langs: ["ts", "sh"] })makes one with Shiki. - Feeds:
rss({ title, link, description, items }), an RSS 2.0 feed with its links made absolute.
Checked when saved
A collection says it is one (by Symbol.for("tcm.collection")), so tcm asks it about each file saved into its
namespace, and refuses one that doesn't fit, saying why (content collections).
Its versions follow semver from its API, as any package's do (releases).