Edit any note and its images from the admin page

Every note gets an Edit form built from its note type's schema: image
fields show a thumbnail with a pick from the vault or an upload, link
fields offer note names, and lists of rows can be added to, removed and
reordered. A new Site pages view lists each page of the site with its
text and images and the notes that fill it. Image and link fields now
carry a JSON Schema format so a form knows to offer a picker.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012aSbo2D1qP8cMFQCykf7kx
This commit is contained in:
Claude
2026-10-18 14:19:38 +00:00
parent 5077aeacfd
commit 0f78505e99
10 changed files with 781 additions and 10 deletions
+6 -4
View File
@@ -3,7 +3,9 @@
*
* Each field carries `title` and `description` metadata. The JSON Schema
* export keeps them, so the MCP server, the admin page and any later editor
* can render a form or explain a field without a second definition.
* can render a form or explain a field without a second definition. Image
* and link fields also carry a `format` (`vault-image`, `vault-link`,
* `vault-links`) so a form knows to offer a picker.
*/
import { z } from "zod";
import { normalizeWikilinkInput, wikilinkTarget } from "./names.ts";
@@ -30,7 +32,7 @@ export const wikilink = (meta: Meta) =>
normalizeWikilinkInput,
z.string().refine((v) => wikilinkTarget(v) !== null, "Write a link as [[Note name]]"),
)
.meta(meta);
.meta({ format: "vault-link", ...meta });
/** A list of links to other notes. */
export const wikilinks = (meta: Meta) =>
@@ -39,7 +41,7 @@ export const wikilinks = (meta: Meta) =>
(v) => (Array.isArray(v) ? v.map(normalizeWikilinkInput) : v),
z.array(z.string().refine((v) => wikilinkTarget(v) !== null, "Write each link as [[Note name]]")),
)
.meta(meta);
.meta({ format: "vault-links", ...meta });
/** An image: a vault attachment as `[[file.jpg]]`, or a full https URL. */
export const image = (meta: Meta) =>
@@ -53,7 +55,7 @@ export const image = (meta: Meta) =>
"Use a vault image as [[file.jpg]] or a full https URL",
),
)
.meta(meta);
.meta({ format: "vault-image", ...meta });
/** One short line of text. */
export const line = (meta: Meta) => z.string().trim().min(1).meta(meta);