@marktiderman/genesis-sites 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +241 -13
  2. package/dist/assets/islands.77d11f5697.js +1 -0
  3. package/dist/assets/sites-forms.732cc7e0c1.css +10 -0
  4. package/dist/assets/sites-forms.css +1 -1
  5. package/dist/assets/sites.716b4ac1a5.css +2 -0
  6. package/dist/assets/sites.css +1 -1
  7. package/dist/assets.generated-QSB7EJWX.js +3 -0
  8. package/dist/assets.generated-QSB7EJWX.js.map +1 -0
  9. package/dist/blocks.d.ts +1 -1
  10. package/dist/blocks.js +5 -1
  11. package/dist/blocks.js.map +1 -1
  12. package/dist/chunk-3VKTBE7S.js +69 -0
  13. package/dist/chunk-3VKTBE7S.js.map +1 -0
  14. package/dist/chunk-5IXDFFEG.js +465 -0
  15. package/dist/chunk-5IXDFFEG.js.map +1 -0
  16. package/dist/chunk-C375ZPU2.js +2241 -0
  17. package/dist/chunk-C375ZPU2.js.map +1 -0
  18. package/dist/{chunk-GA7U3CIN.js → chunk-FBQF2L7O.js} +317 -97
  19. package/dist/chunk-FBQF2L7O.js.map +1 -0
  20. package/dist/chunk-H6ED3K4R.js +18 -0
  21. package/dist/chunk-H6ED3K4R.js.map +1 -0
  22. package/dist/chunk-KPOX7D4S.js +250 -0
  23. package/dist/chunk-KPOX7D4S.js.map +1 -0
  24. package/dist/chunk-VZUDRPFG.js +13 -0
  25. package/dist/chunk-VZUDRPFG.js.map +1 -0
  26. package/dist/{chunk-KEF3V5ZN.js → chunk-ZGWGQGT2.js} +169 -73
  27. package/dist/chunk-ZGWGQGT2.js.map +1 -0
  28. package/dist/editor.d.ts +526 -0
  29. package/dist/editor.js +2480 -0
  30. package/dist/editor.js.map +1 -0
  31. package/dist/handler-QHH453YG.js +9 -0
  32. package/dist/handler-QHH453YG.js.map +1 -0
  33. package/dist/import.d.ts +130 -0
  34. package/dist/import.js +330 -0
  35. package/dist/import.js.map +1 -0
  36. package/dist/index.d.ts +47 -8
  37. package/dist/index.js +5 -250
  38. package/dist/index.js.map +1 -1
  39. package/dist/{registry-CdgVymsu.d.ts → registry-HBn1X60x.d.ts} +274 -8
  40. package/dist/sections.d.ts +422 -6
  41. package/dist/sections.js +4 -2
  42. package/dist/{store-BzGw2i5J.d.ts → store-BXiZeZzH.d.ts} +119 -53
  43. package/dist/supabase.d.ts +5 -5
  44. package/dist/supabase.js +115 -6
  45. package/dist/supabase.js.map +1 -1
  46. package/dist/web.d.ts +26 -8
  47. package/dist/web.js +7 -353
  48. package/dist/web.js.map +1 -1
  49. package/migrations/0001_genesis_sites.sql +64 -6
  50. package/migrations/0002_genesis_sites_posts.sql +404 -0
  51. package/migrations/tests/0001_genesis_sites.test.sql +30 -1
  52. package/migrations/tests/0002_genesis_sites_posts.test.sql +242 -0
  53. package/package.json +28 -10
  54. package/dist/assets/islands.230b20b9c4.js +0 -1
  55. package/dist/assets/sites-forms.5e6ebf31c3.css +0 -10
  56. package/dist/assets/sites.b28b796c6f.css +0 -2
  57. package/dist/chunk-43XUAO63.js +0 -1255
  58. package/dist/chunk-43XUAO63.js.map +0 -1
  59. package/dist/chunk-GA7U3CIN.js.map +0 -1
  60. package/dist/chunk-KEF3V5ZN.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/core/urls.ts","../src/core/schemas.ts","../src/core/registry.ts","../src/core/seo.ts"],"names":["z"],"mappings":"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","file":"chunk-KEF3V5ZN.js","sourcesContent":["/**\n * URL and path rules shared by the schemas, the renderer and the database.\n *\n * Every link a site renders comes from stored props, so every link is\n * untrusted. A link is safe when it is a site path (`/about`), a fragment\n * (`#pricing`), or an absolute `https:`, `http:`, `mailto:` or `tel:` URL.\n * Everything else (`javascript:`, `data:`, `vbscript:`, protocol-relative\n * `//host`, a backslash trick, a control character) is refused, both when a\n * document is parsed and again when it is rendered.\n */\n\n/** The longest URL a site stores. */\nexport const MAX_URL_LENGTH = 2048;\n\nconst SAFE_SCHEMES = new Set([\"https:\", \"http:\", \"mailto:\", \"tel:\"]);\n// C0 controls, DEL, whitespace other than a plain space, and the backslash\n// (browsers read `\\` as `/` in special URLs, so `/\\evil.test` is `//evil.test`).\n// eslint-disable-next-line no-control-regex\nconst UNSAFE_CHARS = /[\\u0000-\\u001f\\u007f\\\\\\s]/;\n\n/** Is this a link a site may render: a site path, a fragment, or an http(s), mailto or tel URL? */\nexport function isSafeHref(value: unknown): value is string {\n if (typeof value !== \"string\" || value.length === 0 || value.length > MAX_URL_LENGTH) return false;\n if (UNSAFE_CHARS.test(value)) return false;\n if (value.startsWith(\"#\")) return true;\n if (value.startsWith(\"/\")) return !value.startsWith(\"//\");\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n return false;\n }\n if (!SAFE_SCHEMES.has(url.protocol)) return false;\n if (url.protocol === \"http:\" || url.protocol === \"https:\") return url.hostname.length > 0 && !url.username && !url.password;\n return true;\n}\n\n/** Is this a URL an image may load from: a site path or an `https:` URL? */\nexport function isSafeImageSrc(value: unknown): value is string {\n if (!isSafeHref(value)) return false;\n if (value.startsWith(\"/\")) return true;\n return value.startsWith(\"https://\");\n}\n\n/** Is this an external (absolute) link, opened with `rel=\"noopener noreferrer\"`? */\nexport function isExternalHref(href: string): boolean {\n return /^https?:\\/\\//i.test(href);\n}\n\n/**\n * A page's path: `/`, or lowercase segments of letters, digits and hyphens\n * (`/about`, `/classes/strength`). No trailing slash, no dots, at most 8\n * segments and 200 characters. The database checks the same pattern.\n */\nexport const PAGE_PATH = /^\\/(?:[a-z0-9]+(?:-[a-z0-9]+)*(?:\\/[a-z0-9]+(?:-[a-z0-9]+)*){0,7})?$/;\nexport const MAX_PAGE_PATH_LENGTH = 200;\n\n/**\n * Paths a site never owns, because it shares its hostname with the host app:\n * the app's API and server functions, its auth callbacks, and this package's\n * own assets. A host passes its own list (or a predicate) to\n * `handleSiteRequest` and `validatePagePath`; the database's default is the\n * same list (`genesis_sites.reserved_paths()`).\n */\nexport const DEFAULT_RESERVED_PATHS: readonly string[] = Object.freeze([\"/api\", \"/_server\", \"/auth\", \"/_gs\"]);\n\n/** A reserved-path rule: a list of path prefixes, or a predicate. */\nexport type ReservedPaths = readonly string[] | ((path: string) => boolean);\n\n/** Is `path` reserved: equal to a reserved prefix, or under it (`/api`, `/api/x`, not `/apiary`)? */\nexport function isReservedPath(path: string, reserved: ReservedPaths = DEFAULT_RESERVED_PATHS): boolean {\n if (typeof reserved === \"function\") return reserved(path);\n return reserved.some((prefix) => {\n const p = prefix.endsWith(\"/\") && prefix.length > 1 ? prefix.slice(0, -1) : prefix;\n return path === p || path.startsWith(`${p}/`);\n });\n}\n\n/** Problems with a page path, empty when it is fine. */\nexport function pagePathProblems(path: unknown, reserved: ReservedPaths = DEFAULT_RESERVED_PATHS): string[] {\n if (typeof path !== \"string\") return [\"A page path is text.\"];\n const problems: string[] = [];\n if (path.length > MAX_PAGE_PATH_LENGTH) problems.push(`A page path has at most ${MAX_PAGE_PATH_LENGTH} characters.`);\n if (!PAGE_PATH.test(path)) {\n problems.push('A page path starts with \"/\" and uses lowercase letters, digits and single hyphens, with no trailing slash (for example \"/about\").');\n }\n if (isReservedPath(path, reserved)) problems.push(`\"${path}\" is reserved for the app this site shares its address with.`);\n return problems;\n}\n\n/** Throws when the path can't be a page's. */\nexport function validatePagePath(path: string, reserved: ReservedPaths = DEFAULT_RESERVED_PATHS): string {\n const problems = pagePathProblems(path, reserved);\n if (problems.length) throw new Error(problems.join(\" \"));\n return path;\n}\n\n/**\n * The page path a request path asks for: decoded, lowercase, without a\n * trailing slash. Returns null for a path that can't name a page (so the\n * caller falls through to the host app).\n */\nexport function normalizeRequestPath(pathname: string): string | null {\n let path: string;\n try {\n path = decodeURIComponent(pathname);\n } catch {\n return null;\n }\n if (UNSAFE_CHARS.test(path) || path.includes(\"//\")) return null;\n if (path.length > 1 && path.endsWith(\"/\")) path = path.slice(0, -1);\n return path.toLowerCase();\n}\n","/**\n * The documents a site is made of, as zod 4 schemas: a `SiteDoc` (theme,\n * header, navigation, footer, SEO defaults, redirects), one `PageDoc` per\n * page (its sections and SEO), and the `ReleaseSnapshot` a publish freezes.\n *\n * A page's `content` is an array of `{ id, type, v, variant, props }`\n * section nodes, which is the shape Puck's `content` uses, so the editor\n * reads and writes these documents unchanged. A section's `props` are\n * checked by that section's own schema (see `defineSection`), not here.\n */\nimport { z } from \"zod\";\nimport { MAX_URL_LENGTH, PAGE_PATH, isSafeHref, isSafeImageSrc } from \"./urls\";\n\n/** zod 4 is required: `z.toJSONSchema` (editor fields, AI output) exists only there. */\nif (typeof (z as { toJSONSchema?: unknown }).toJSONSchema !== \"function\") {\n throw new Error(\"@marktiderman/genesis-sites needs zod 4 (zod@^4.0.0): z.toJSONSchema is missing.\");\n}\n\n// ── Building blocks for section schemas ─────────────────────────────────────\n\n/** A link target: a site path, a fragment, or an http(s), mailto or tel URL. */\nexport const Href = z\n .string()\n .max(MAX_URL_LENGTH)\n .refine(isSafeHref, { message: \"Use a site path (/about), a #section, or an https, mailto or tel link.\" })\n .meta({ title: \"Link\", format: \"uri-reference\" });\n\n/** A labelled link: a button, a menu entry, a footer link. */\nexport const Link = z\n .object({\n label: z.string().trim().min(1).max(80),\n href: Href,\n /** Opens in a new tab (external links only). */\n newTab: z.boolean().optional(),\n })\n .meta({ title: \"Link\" });\nexport type Link = z.infer<typeof Link>;\n\n/**\n * An image. `alt` describes it for someone who can't see it; an image that\n * adds nothing (a texture) is `decorative: true` and gets an empty alt. The\n * accessibility check refuses to publish an image with neither.\n */\nexport const Image = z\n .object({\n src: z\n .string()\n .max(MAX_URL_LENGTH)\n .refine(isSafeImageSrc, { message: \"An image loads from a site path or an https URL.\" }),\n alt: z.string().max(300).default(\"\"),\n decorative: z.boolean().optional(),\n width: z.number().int().positive().max(10000).optional(),\n height: z.number().int().positive().max(10000).optional(),\n /** Where the subject is, for cropping: 0–100 from the left and top. */\n focal: z.object({ x: z.number().min(0).max(100), y: z.number().min(0).max(100) }).optional(),\n })\n .meta({ title: \"Image\", \"x-genesis-kind\": \"image\" });\nexport type Image = z.infer<typeof Image>;\n\n/**\n * Rich text: the JSON genesis-ui's `RichTextEditor` (TipTap) produces. Only\n * its outline is checked here; genesis-ui's `RichText` sanitizes it again\n * when it renders, so a stored document can never carry raw HTML.\n */\nexport const RichText = z\n .object({\n type: z.literal(\"doc\"),\n content: z.array(z.record(z.string(), z.unknown())).max(2000).optional(),\n })\n .meta({ title: \"Rich text\", \"x-genesis-kind\": \"rich-text\" });\nexport type RichText = z.infer<typeof RichText>;\n\n/** The band a section sits on. */\nexport const Surface = z.enum([\"base\", \"muted\", \"accent\", \"inverse\"]).meta({ title: \"Background\" });\nexport type Surface = z.infer<typeof Surface>;\n\n/** A short line of copy (a heading, a label). */\nexport const Line = (max = 120) => z.string().trim().min(1).max(max);\n/** A paragraph of plain copy. */\nexport const Copy = (max = 600) => z.string().trim().max(max);\n\n// ── Section nodes and pages ─────────────────────────────────────────────────\n\n/** A section's id: stable, letters, digits, `-` and `_` (Shopify's rule). */\nexport const SectionId = z.string().regex(/^[A-Za-z0-9_-]{1,64}$/, \"A section id is 1–64 letters, digits, - or _.\");\n\nexport const SectionNode = z.object({\n id: SectionId,\n /** The section's registry key, such as `hero`. */\n type: z.string().regex(/^[a-z][a-z0-9-]{0,63}$/),\n /** The props version the props were written at; `migrateNode` brings them up to date. */\n v: z.number().int().min(1),\n variant: z.string().max(64).optional(),\n /** Kept in the page, not rendered (Shopify's `disabled`). */\n hidden: z.boolean().optional(),\n /** Hidden on phones or on wider screens. */\n hideOn: z.array(z.enum([\"mobile\", \"desktop\"])).max(2).optional(),\n /**\n * Set by a template on content someone must replace (a sample quote). The\n * publish check refuses a visible section that still has it; the editor\n * clears it once the section is edited.\n */\n placeholder: z.boolean().optional(),\n props: z.record(z.string(), z.unknown()),\n});\nexport type SectionNode = z.infer<typeof SectionNode>;\n\nexport const Seo = z.object({\n title: z.string().trim().max(70).optional(),\n description: z.string().trim().max(200).optional(),\n ogImage: Image.optional(),\n /** An absolute canonical URL, when this page's content lives elsewhere. */\n canonical: z.url({ protocol: /^https?$/ }).max(MAX_URL_LENGTH).optional(),\n noindex: z.boolean().optional(),\n});\nexport type Seo = z.infer<typeof Seo>;\n\nexport const PageDoc = z.object({\n schemaVersion: z.literal(1),\n root: z.object({\n props: z.looseObject({\n title: z.string().trim().min(1).max(120),\n /** Leave out the site's header and footer (a focused landing page). */\n hideSiteChrome: z.boolean().optional(),\n }),\n }),\n content: z.array(SectionNode).max(60),\n seo: Seo.optional(),\n});\nexport type PageDoc = z.infer<typeof PageDoc>;\n\nexport const PageKind = z.enum([\"page\", \"landing\"]);\nexport type PageKind = z.infer<typeof PageKind>;\n\nexport const PagePath = z.string().max(200).regex(PAGE_PATH, 'A page path looks like \"/\" or \"/about\".');\n\n// ── The site ────────────────────────────────────────────────────────────────\n\nexport const MenuItem = z.object({\n label: z.string().trim().min(1).max(40),\n href: Href,\n});\nexport type MenuItem = z.infer<typeof MenuItem>;\n\nexport const Redirect = z.object({\n from: PagePath,\n to: Href,\n status: z.union([z.literal(301), z.literal(302)]),\n});\nexport type Redirect = z.infer<typeof Redirect>;\n\n/** Fonts a site may choose; see `FONT_CHOICES` in theme.ts for their stacks. */\nexport const FontChoice = z.enum([\n \"system\",\n \"inter\",\n \"dm-sans\",\n \"work-sans\",\n \"montserrat\",\n \"poppins\",\n \"space-grotesk\",\n \"source-serif\",\n \"merriweather\",\n \"playfair-display\",\n \"lora\",\n]);\nexport type FontChoice = z.infer<typeof FontChoice>;\n\n/**\n * A site's theme choices on top of the brand: token choices only, never raw\n * CSS, so a site stays inside the design system.\n */\nexport const TokenOverrides = z.object({\n radius: z.enum([\"none\", \"sm\", \"md\", \"lg\", \"full\"]).optional(),\n headingFont: FontChoice.optional(),\n bodyFont: FontChoice.optional(),\n});\nexport type TokenOverrides = z.infer<typeof TokenOverrides>;\n\nexport const SeoDefaults = z.object({\n /** `%s` is the page's title: `\"%s · Riverside Gym\"`. */\n titleTemplate: z.string().max(80).optional(),\n description: z.string().trim().max(200).optional(),\n ogImage: Image.optional(),\n /** Organization facts for JSON-LD. */\n organization: z\n .object({\n name: z.string().trim().min(1).max(120),\n logo: z.string().max(MAX_URL_LENGTH).refine(isSafeImageSrc).optional(),\n sameAs: z.array(z.url({ protocol: /^https$/ }).max(MAX_URL_LENGTH)).max(10).optional(),\n })\n .optional(),\n noindex: z.boolean().optional(),\n});\nexport type SeoDefaults = z.infer<typeof SeoDefaults>;\n\nexport const SiteDoc = z.object({\n schemaVersion: z.literal(1),\n name: z.string().trim().min(1).max(120),\n /** BCP 47 language of the site's pages. */\n lang: z.string().regex(/^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/).default(\"en\"),\n theme: z\n .object({\n colorScheme: z.enum([\"light\", \"dark\", \"auto\"]).default(\"light\"),\n overrides: TokenOverrides.optional(),\n })\n .default({ colorScheme: \"light\" }),\n /** The site's header: usually one `nav` section. */\n header: z.array(SectionNode).max(2).default([]),\n /** The header's menu. */\n nav: z.array(MenuItem).max(12).default([]),\n /** The site's footer: usually one `footer` section. */\n footer: z.array(SectionNode).max(3).default([]),\n seo: SeoDefaults.default({}),\n redirects: z.array(Redirect).max(500).default([]),\n});\nexport type SiteDoc = z.infer<typeof SiteDoc>;\n/** A `SiteDoc` as written, before defaults. */\nexport type SiteDocInput = z.input<typeof SiteDoc>;\n\n// ── Releases ────────────────────────────────────────────────────────────────\n\nexport const ReleasePage = z.object({\n id: z.string().min(1),\n path: PagePath,\n kind: PageKind,\n doc: PageDoc,\n});\nexport type ReleasePage = z.infer<typeof ReleasePage>;\n\n/** Everything a published site serves: the site document and every page, frozen at publish. */\nexport const ReleaseSnapshot = z.object({\n schemaVersion: z.literal(1),\n site: SiteDoc,\n pages: z.array(ReleasePage).max(500),\n});\nexport type ReleaseSnapshot = z.infer<typeof ReleaseSnapshot>;\n\n/**\n * Read a stored snapshot page by page: a page that no longer parses (a\n * schema this release tightened, a document written past the checks) is\n * left out and reported, so one bad page doesn't take the whole site down.\n * Null only when the site document itself doesn't parse.\n */\nexport function parseSnapshot(value: unknown, report: (message: string) => void = (m) => console.error(`[genesis-sites] ${m}`)): ReleaseSnapshot | null {\n const raw = value && typeof value === \"object\" ? (value as { schemaVersion?: unknown; site?: unknown; pages?: unknown }) : {};\n if (raw.schemaVersion !== 1) {\n report(\"the snapshot isn't schemaVersion 1.\");\n return null;\n }\n const site = SiteDoc.safeParse(raw.site);\n if (!site.success) {\n report(`the snapshot's site document doesn't parse: ${site.error.message}`);\n return null;\n }\n const pages: ReleasePage[] = [];\n for (const page of Array.isArray(raw.pages) ? raw.pages.slice(0, 500) : []) {\n const parsed = ReleasePage.safeParse(page);\n if (parsed.success) pages.push(parsed.data);\n else report(`the page ${JSON.stringify((page as { path?: unknown })?.path ?? \"?\")} doesn't parse and is left out: ${parsed.error.message}`);\n }\n return { schemaVersion: 1, site: site.data, pages };\n}\n\nexport interface ReleaseMeta {\n id: string;\n siteId: string;\n number: number;\n note: string | null;\n createdAt: string;\n publishedAt: string | null;\n /** The brand the release was checked against (`brandHash`), when known. */\n brandHash: string | null;\n}\n\nexport interface Release extends ReleaseMeta {\n snapshot: ReleaseSnapshot;\n}\n\nexport interface PageMeta {\n id: string;\n siteId: string;\n path: string;\n kind: PageKind;\n title: string;\n sort: number;\n rev: number;\n}\n\n/** The size limit of one stored document, as the database enforces it (512 KiB of JSON). */\nexport const MAX_DOC_BYTES = 512 * 1024;\n","/**\n * Sections: `defineSection` describes one kind of section (its props schema,\n * variants, presets, migrations and server-safe React renderer), and the\n * registry holds every kind a site can use.\n *\n * Modelled on genesis-forms' `registerContentType`: one registry per process,\n * kept on a `Symbol.for` global so two copies of this package (a host's and a\n * dependency's) share it; manifests are frozen; a host adds its own kinds and\n * replaces a built-in only with `{ replace: true }`.\n *\n * Everything the editor needs comes from the definition: `label`,\n * `category`, `variants`, `presets` and `sectionJsonSchema(type)`\n * (`z.toJSONSchema` of the props schema) for its fields and for AI output.\n */\nimport type { ReactNode } from \"react\";\nimport { z } from \"zod\";\nimport type { MenuItem, PageKind, SectionNode } from \"./schemas\";\nimport type { ResolvedForm } from \"./forms\";\n\nexport const SECTION_CATEGORIES = [\"header\", \"intro\", \"content\", \"social-proof\", \"conversion\", \"footer\"] as const;\nexport type SectionCategory = (typeof SECTION_CATEGORIES)[number];\n\n/** Where on a page a section may go: the site header, the page body, or the site footer. */\nexport type SectionPlacement = \"header\" | \"body\" | \"footer\";\n\nexport interface SectionVariant {\n id: string;\n label: string;\n}\n\nexport interface SectionPreset<P = Record<string, unknown>> {\n /** Shown in the editor's Add picker. */\n name: string;\n variant: string;\n props: P;\n}\n\n/** What a section's renderer is told about the page it is on. */\nexport interface RenderContext {\n /**\n * The level of the section's title: 1 for the page's main heading (the\n * first section that `providesH1`), 2 for every other section. Items in a\n * section are one level below it.\n */\n headingLevel: 1 | 2;\n site: {\n name: string;\n lang: string;\n nav: readonly MenuItem[];\n logo?: { src: string; alt: string } | undefined;\n };\n /** The page's own path, such as `/about`. */\n pagePath: string;\n /** A stored link as the page should print it: site paths get the host's base path. */\n href(href: string): string;\n /** Forms on the page, resolved by slug before rendering (null: the host doesn't know the slug). */\n forms: ReadonlyMap<string, ResolvedForm | null>;\n mode: \"live\" | \"preview\";\n /** A prefix that makes ids unique on the page: the section node's id. */\n idPrefix: string;\n}\n\nexport interface SectionRenderProps<P> {\n props: P;\n variant: string;\n node: SectionNode;\n ctx: RenderContext;\n}\n\nexport interface SectionDefinition<P = Record<string, unknown>> {\n /** The registry key stored in each node: lowercase, such as `hero`. */\n type: string;\n /** The current props version. Nodes at a lower `v` are migrated on read. */\n version: number;\n label: string;\n description?: string;\n category: SectionCategory;\n /** The props schema (zod 4). Its input type is what an editor writes. */\n schema: z.ZodType<P>;\n variants: readonly SectionVariant[];\n defaultVariant: string;\n presets: readonly SectionPreset<z.input<z.ZodType<P>>>[];\n /** At most this many on a page. */\n limit?: number;\n /** The page kinds it may appear on (default: every kind). */\n enabledOn?: readonly PageKind[];\n /** Where it may go (default: the page body). */\n placement?: SectionPlacement;\n /** Its title is the page's `h1` when it comes first (a hero). */\n providesH1?: boolean;\n /**\n * `migrations[n]` turns version `n - 1` props into version `n` props. Pure\n * functions: `migrateNode` runs them in order on read, in the editor and in\n * the renderer, and a publish writes the result into the release.\n */\n migrations?: Readonly<Record<number, (props: Record<string, unknown>) => Record<string, unknown>>>;\n /** Server-safe React: no state, no effects, no browser APIs. */\n render: (input: SectionRenderProps<P>) => ReactNode;\n}\n\n/** A definition as the registry holds it: props erased to a record. */\nexport type AnySectionDefinition = SectionDefinition<any>; // eslint-disable-line @typescript-eslint/no-explicit-any\n\nexport class SectionDefinitionError extends Error {\n constructor(readonly problems: string[]) {\n super(`Invalid section definition:\\n${problems.map((p) => ` - ${p}`).join(\"\\n\")}`);\n this.name = \"SectionDefinitionError\";\n }\n}\n\nconst TYPE = /^[a-z][a-z0-9-]{0,63}$/;\n\nfunction definitionProblems(def: AnySectionDefinition): string[] {\n const problems: string[] = [];\n if (!def || typeof def !== \"object\") return [\"a section definition is an object\"];\n const at = typeof def.type === \"string\" ? `\"${def.type}\"` : \"a section\";\n if (typeof def.type !== \"string\" || !TYPE.test(def.type)) problems.push(`${at}: \\`type\\` is lowercase letters, digits and -`);\n if (!Number.isInteger(def.version) || def.version < 1) problems.push(`${at}: \\`version\\` is a whole number from 1`);\n if (typeof def.label !== \"string\" || !def.label.trim()) problems.push(`${at}: needs a \\`label\\``);\n if (!(SECTION_CATEGORIES as readonly string[]).includes(def.category)) problems.push(`${at}: \\`category\\` is one of ${SECTION_CATEGORIES.join(\", \")}`);\n if (!def.schema || typeof (def.schema as { safeParse?: unknown }).safeParse !== \"function\") problems.push(`${at}: \\`schema\\` is a zod schema`);\n if (typeof def.render !== \"function\") problems.push(`${at}: \\`render\\` is a function`);\n const ids = new Set<string>();\n if (!Array.isArray(def.variants) || def.variants.length === 0) problems.push(`${at}: needs at least one variant`);\n else\n for (const v of def.variants) {\n if (!v || typeof v.id !== \"string\" || !/^[a-z][a-z0-9-]{0,63}$/.test(v.id) || typeof v.label !== \"string\") problems.push(`${at}: a variant is { id, label }`);\n else if (ids.has(v.id)) problems.push(`${at}: variant \"${v.id}\" is listed twice`);\n else ids.add(v.id);\n }\n if (!ids.has(def.defaultVariant)) problems.push(`${at}: \\`defaultVariant\\` \"${String(def.defaultVariant)}\" is not one of its variants`);\n if (def.limit !== undefined && (!Number.isInteger(def.limit) || def.limit < 1)) problems.push(`${at}: \\`limit\\` is a whole number from 1`);\n if (def.placement !== undefined && ![\"header\", \"body\", \"footer\"].includes(def.placement)) problems.push(`${at}: \\`placement\\` is header, body or footer`);\n for (const [key, fn] of Object.entries(def.migrations ?? {})) {\n const n = Number(key);\n if (!Number.isInteger(n) || n < 2 || n > def.version) problems.push(`${at}: migration ${key} must be between 2 and the version (${def.version})`);\n if (typeof fn !== \"function\") problems.push(`${at}: migration ${key} is a function`);\n }\n for (let n = 2; n <= (Number.isInteger(def.version) ? def.version : 0); n++) {\n if (!def.migrations?.[n]) problems.push(`${at}: version ${def.version} needs a migration to ${n}`);\n }\n if (!Array.isArray(def.presets) || def.presets.length === 0) problems.push(`${at}: needs at least one preset (the editor's Add picker)`);\n else if (def.schema && typeof (def.schema as { safeParse?: unknown }).safeParse === \"function\")\n for (const preset of def.presets) {\n if (!preset || typeof preset.name !== \"string\" || !ids.has(preset.variant)) {\n problems.push(`${at}: preset ${JSON.stringify(preset?.name)} needs a name and one of its variants`);\n continue;\n }\n const parsed = def.schema.safeParse(preset.props);\n if (!parsed.success) problems.push(`${at}: preset \"${preset.name}\" doesn't match the schema: ${parsed.error.issues.map((i) => `${i.path.join(\".\") || \"props\"} ${i.message}`).join(\"; \")}`);\n }\n return problems;\n}\n\n/**\n * Declare a section kind. Checks the definition (and every preset against its\n * schema) and returns it frozen. It isn't registered until `registerSection`.\n *\n * @stability Beta\n */\nexport function defineSection<P>(def: SectionDefinition<P>): Readonly<SectionDefinition<P>> {\n const problems = definitionProblems(def as AnySectionDefinition);\n if (problems.length) throw new SectionDefinitionError(problems);\n return Object.freeze({\n ...def,\n variants: Object.freeze(def.variants.map((v) => Object.freeze({ ...v }))),\n presets: Object.freeze(def.presets.map((p) => Object.freeze({ ...p }))),\n ...(def.enabledOn ? { enabledOn: Object.freeze([...def.enabledOn]) } : {}),\n ...(def.migrations ? { migrations: Object.freeze({ ...def.migrations }) } : {}),\n });\n}\n\n// ── The registry ────────────────────────────────────────────────────────────\n\nconst REGISTRY = Symbol.for(\"@marktiderman/genesis-sites/sections@1\");\nconst BUILT_IN = Symbol.for(\"@marktiderman/genesis-sites/built-in-sections@1\");\ntype Scope = typeof globalThis & { [REGISTRY]?: Map<string, AnySectionDefinition>; [BUILT_IN]?: Set<string> };\nconst scope = globalThis as Scope;\nconst registry: Map<string, AnySectionDefinition> = (scope[REGISTRY] ??= new Map());\nconst builtIns: Set<string> = (scope[BUILT_IN] ??= new Set());\n\n/** The built-in section kinds, which a host replaces only with `{ replace: true }`. */\nexport const BUILT_IN_SECTION_TYPES = Object.freeze([\n \"nav\",\n \"hero\",\n \"features\",\n \"cta\",\n \"testimonials\",\n \"faq\",\n \"pricing\",\n \"logos\",\n \"stats\",\n \"gallery\",\n \"rich-text\",\n \"form-embed\",\n \"footer\",\n] as const);\nexport type BuiltInSectionType = (typeof BUILT_IN_SECTION_TYPES)[number];\n\nexport interface RegisterSectionOptions {\n /** Replace a built-in kind, for every site in this process. */\n replace?: boolean;\n}\n\n/**\n * Register a section kind (from `defineSection`, or a plain definition, which\n * is checked the same way). Re-registering a host kind replaces it, so hot\n * reload works; a built-in kind's name throws unless `{ replace: true }`.\n *\n * @stability Beta\n */\nexport function registerSection(def: AnySectionDefinition, options: RegisterSectionOptions = {}): void {\n const frozen = Object.isFrozen(def) && definitionProblems(def).length === 0 ? def : defineSection(def);\n if ((BUILT_IN_SECTION_TYPES as readonly string[]).includes(frozen.type) && options.replace !== true) {\n throw new Error(\n `registerSection: \"${frozen.type}\" is a built-in section; pass { replace: true } to replace it for every site in this process.`,\n );\n }\n registry.set(frozen.type, frozen);\n}\n\n/** For `@marktiderman/genesis-sites/sections`: register a built-in unless one (or a replacement) is there. @internal */\nexport function registerBuiltInSection(def: AnySectionDefinition): void {\n if (!registry.has(def.type)) registry.set(def.type, def);\n builtIns.add(def.type);\n}\n\nexport function getSection(type: string): AnySectionDefinition | undefined {\n return registry.get(type);\n}\n\nexport function listSections(): AnySectionDefinition[] {\n return [...registry.values()];\n}\n\n/** Remove a host section kind (tests, hot reload). Built-ins can't be removed, only replaced. */\nexport function unregisterSection(type: string): boolean {\n if ((BUILT_IN_SECTION_TYPES as readonly string[]).includes(type)) throw new Error(`unregisterSection: \"${type}\" is built in; replace it with registerSection(…, { replace: true }).`);\n return registry.delete(type);\n}\n\nconst jsonSchemas = new WeakMap<object, Record<string, unknown>>();\n\n/**\n * The JSON Schema of a section's props (`z.toJSONSchema`, input side), for the\n * editor's fields and for validating AI output. Refinements (safe URLs) don't\n * appear in JSON Schema; the zod schema still checks them on save.\n *\n * @stability Beta\n */\nexport function sectionJsonSchema(typeOrDef: string | AnySectionDefinition): Record<string, unknown> {\n const def = typeof typeOrDef === \"string\" ? registry.get(typeOrDef) : typeOrDef;\n if (!def) throw new Error(`sectionJsonSchema: no section \"${String(typeOrDef)}\" is registered.`);\n let schema = jsonSchemas.get(def.schema);\n if (!schema) {\n schema = z.toJSONSchema(def.schema, { io: \"input\", unrepresentable: \"any\" }) as Record<string, unknown>;\n jsonSchemas.set(def.schema, schema);\n }\n return schema;\n}\n\n/** What the editor's Add picker and fields need about one section kind. */\nexport interface SectionManifest {\n type: string;\n version: number;\n label: string;\n description?: string;\n category: SectionCategory;\n placement: SectionPlacement;\n variants: readonly SectionVariant[];\n defaultVariant: string;\n presets: readonly SectionPreset[];\n limit?: number;\n enabledOn?: readonly PageKind[];\n jsonSchema: Record<string, unknown>;\n}\n\n/** Every registered section as editor data (no renderers): the editor's catalog. @stability Beta */\nexport function sectionManifests(): SectionManifest[] {\n return listSections().map((def) => ({\n type: def.type,\n version: def.version,\n label: def.label,\n ...(def.description ? { description: def.description } : {}),\n category: def.category,\n placement: def.placement ?? \"body\",\n variants: def.variants,\n defaultVariant: def.defaultVariant,\n presets: def.presets as readonly SectionPreset[],\n ...(def.limit ? { limit: def.limit } : {}),\n ...(def.enabledOn ? { enabledOn: def.enabledOn } : {}),\n jsonSchema: sectionJsonSchema(def),\n }));\n}\n\nlet counter = 0;\n/** A new section id: short, alphanumeric, unique enough within a page. */\nexport function newSectionId(prefix = \"s\"): string {\n counter = (counter + 1) % 1_000_000;\n const random = Math.random().toString(36).slice(2, 8);\n return `${prefix}${Date.now().toString(36)}${counter.toString(36)}${random}`.slice(0, 64);\n}\n\n/** A section node from a preset: the editor's Add, and templates. */\nexport function nodeFromPreset(type: string, presetName?: string, id = newSectionId(type.replace(/-/g, \"\").slice(0, 6))): SectionNode {\n const def = registry.get(type);\n if (!def) throw new Error(`nodeFromPreset: no section \"${type}\" is registered.`);\n const preset = presetName ? def.presets.find((p) => p.name === presetName) : def.presets[0];\n if (!preset) throw new Error(`nodeFromPreset: \"${type}\" has no preset \"${presetName}\".`);\n return { id, type, v: def.version, variant: preset.variant, props: structuredClone(preset.props) as Record<string, unknown> };\n}\n","/**\n * SEO: a page's meta tags (title, description, canonical, robots, Open Graph,\n * Twitter), sitemap.xml, robots.txt, JSON-LD (Organization, WebSite,\n * BreadcrumbList), and the redirects a page move leaves behind.\n *\n * Canonical and absolute URLs are built from `origin`, the site's primary\n * address, which the host passes in. Nothing here reads a request's Host.\n */\nimport type { Image, PageDoc, Redirect, ReleasePage, SiteDoc } from \"./schemas\";\nimport { isSafeHref } from \"./urls\";\n\nexport interface PageMetaInput {\n site: SiteDoc;\n page: ReleasePage;\n /** The site's primary origin, `https://riverside.example`, no trailing slash. */\n origin: string;\n /** The path prefix the site is served under (`\"\"` at the root). */\n basePath?: string;\n /** A preview: always `noindex`. */\n preview?: boolean;\n}\n\nexport interface PageMeta {\n title: string;\n description?: string;\n canonical: string;\n robots: string;\n openGraph: Record<string, string>;\n twitter: Record<string, string>;\n}\n\n/** The absolute URL of a site path. */\nexport function absoluteUrl(origin: string, basePath: string, path: string): string {\n const base = origin.replace(/\\/+$/, \"\") + (basePath ?? \"\").replace(/\\/+$/, \"\");\n return path === \"/\" ? `${base}/` : `${base}${path}`;\n}\n\nfunction imageUrl(image: Image | undefined, origin: string, basePath: string): string | undefined {\n if (!image) return undefined;\n return image.src.startsWith(\"/\") ? absoluteUrl(origin, basePath, image.src) : image.src;\n}\n\n/**\n * The page's title with the site's template (`%s · Riverside Gym`), so every\n * tab and search result names the site. An SEO title written for the page\n * (`seo.title`) is used as it is.\n */\nexport function pageTitle(site: SiteDoc, doc: PageDoc, _path: string): string {\n const own = doc.seo?.title?.trim();\n if (own) return own;\n const title = doc.root.props.title;\n const template = site.seo.titleTemplate;\n if (!template || !template.includes(\"%s\")) return title;\n return template.replace(\"%s\", title);\n}\n\n/** Every meta value a page prints in its `<head>`. */\nexport function pageMeta({ site, page, origin, basePath = \"\", preview = false }: PageMetaInput): PageMeta {\n const doc = page.doc;\n const title = pageTitle(site, doc, page.path);\n const description = doc.seo?.description?.trim() || site.seo.description?.trim() || undefined;\n const canonical = doc.seo?.canonical ?? absoluteUrl(origin, basePath, page.path);\n const noindex = preview || site.seo.noindex === true || doc.seo?.noindex === true;\n const image = doc.seo?.ogImage ?? site.seo.ogImage;\n const img = imageUrl(image, origin, basePath);\n const openGraph: Record<string, string> = {\n \"og:type\": \"website\",\n \"og:title\": title,\n \"og:url\": canonical,\n \"og:site_name\": site.name,\n \"og:locale\": site.lang.replace(\"-\", \"_\"),\n };\n if (description) openGraph[\"og:description\"] = description;\n if (img) {\n openGraph[\"og:image\"] = img;\n if (image?.alt) openGraph[\"og:image:alt\"] = image.alt;\n if (image?.width) openGraph[\"og:image:width\"] = String(image.width);\n if (image?.height) openGraph[\"og:image:height\"] = String(image.height);\n }\n const twitter: Record<string, string> = { \"twitter:card\": img ? \"summary_large_image\" : \"summary\", \"twitter:title\": title };\n if (description) twitter[\"twitter:description\"] = description;\n if (img) twitter[\"twitter:image\"] = img;\n return {\n title,\n ...(description ? { description } : {}),\n canonical,\n robots: noindex ? \"noindex, nofollow\" : \"index, follow\",\n openGraph,\n twitter,\n };\n}\n\n// ── JSON-LD ─────────────────────────────────────────────────────────────────\n\nexport function organizationJsonLd(site: SiteDoc, origin: string, basePath = \"\"): Record<string, unknown> {\n const org = site.seo.organization;\n const out: Record<string, unknown> = {\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n name: org?.name ?? site.name,\n url: absoluteUrl(origin, basePath, \"/\"),\n };\n if (org?.logo) out.logo = org.logo.startsWith(\"/\") ? absoluteUrl(origin, basePath, org.logo) : org.logo;\n if (org?.sameAs?.length) out.sameAs = org.sameAs;\n return out;\n}\n\nexport function websiteJsonLd(site: SiteDoc, origin: string, basePath = \"\"): Record<string, unknown> {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebSite\",\n name: site.name,\n url: absoluteUrl(origin, basePath, \"/\"),\n inLanguage: site.lang,\n };\n}\n\n/** The trail from the home page to `page`, through every ancestor path that is a page. */\nexport function breadcrumbJsonLd(pages: readonly ReleasePage[], page: ReleasePage, origin: string, basePath = \"\"): Record<string, unknown> | null {\n if (page.path === \"/\") return null;\n const byPath = new Map(pages.map((p) => [p.path, p]));\n const trail: ReleasePage[] = [];\n const home = byPath.get(\"/\");\n if (home) trail.push(home);\n const segments = page.path.split(\"/\").filter(Boolean);\n for (let i = 1; i <= segments.length; i++) {\n const ancestor = byPath.get(`/${segments.slice(0, i).join(\"/\")}`);\n if (ancestor) trail.push(ancestor);\n }\n if (trail.length < 2) return null;\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n itemListElement: trail.map((p, i) => ({\n \"@type\": \"ListItem\",\n position: i + 1,\n name: p.doc.root.props.title,\n item: absoluteUrl(origin, basePath, p.path),\n })),\n };\n}\n\n/**\n * JSON for a `<script type=\"application/ld+json\">` (or any JSON inside HTML):\n * `<`, `>`, `&` and the line separators are escaped as `\\uXXXX`, so stored\n * text can never close the script element or open a comment.\n */\nexport function safeJsonForHtml(value: unknown): string {\n return JSON.stringify(value)\n .replace(/</g, \"\\\\u003c\")\n .replace(/>/g, \"\\\\u003e\")\n .replace(/&/g, \"\\\\u0026\")\n .replace(/\\u2028/g, \"\\\\u2028\")\n .replace(/\\u2029/g, \"\\\\u2029\");\n}\n\n// ── sitemap.xml and robots.txt ──────────────────────────────────────────────\n\nexport function escapeXml(text: string): string {\n return text.replace(/[<>&'\"]/g, (c) => ({ \"<\": \"&lt;\", \">\": \"&gt;\", \"&\": \"&amp;\", \"'\": \"&apos;\", '\"': \"&quot;\" })[c]!);\n}\n\nexport interface SitemapInput {\n site: SiteDoc;\n pages: readonly ReleasePage[];\n origin: string;\n basePath?: string;\n /** The release's publish time, as every page's `lastmod`. */\n lastModified?: string | null;\n}\n\n/** sitemap.xml: every indexable page (not `noindex`, not one whose canonical points elsewhere). */\nexport function sitemapXml({ site, pages, origin, basePath = \"\", lastModified }: SitemapInput): string {\n const urls = site.seo.noindex\n ? []\n : pages\n .filter((p) => !p.doc.seo?.noindex && !p.doc.seo?.canonical)\n .sort((a, b) => (a.path === \"/\" ? -1 : b.path === \"/\" ? 1 : a.path.localeCompare(b.path)))\n .map((p) => {\n const loc = `<loc>${escapeXml(absoluteUrl(origin, basePath, p.path))}</loc>`;\n const mod = lastModified ? `<lastmod>${escapeXml(new Date(lastModified).toISOString())}</lastmod>` : \"\";\n return `<url>${loc}${mod}</url>`;\n });\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">${urls.join(\"\")}</urlset>\\n`;\n}\n\nexport interface RobotsInput {\n origin: string;\n basePath?: string;\n /** `Disallow: /` for everyone: a site that is `noindex`, or a preview. */\n disallowAll?: boolean;\n}\n\nexport function robotsTxt({ origin, basePath = \"\", disallowAll = false }: RobotsInput): string {\n const lines = [\"User-agent: *\", disallowAll ? \"Disallow: /\" : \"Allow: /\"];\n if (!disallowAll) lines.push(\"\", `Sitemap: ${absoluteUrl(origin, basePath, \"/sitemap.xml\")}`);\n return `${lines.join(\"\\n\")}\\n`;\n}\n\n// ── Redirects ───────────────────────────────────────────────────────────────\n\n/**\n * The redirects after a page moves from `from` to `to`: a permanent redirect\n * from the old path, earlier redirects to the old path pointed straight at\n * the new one (no chains), and any redirect away from the new path dropped\n * (a page lives there now). A move back undoes the earlier redirect.\n */\nexport function redirectsAfterMove(redirects: readonly Redirect[], from: string, to: string): Redirect[] {\n if (from === to) return [...redirects];\n const next = redirects\n .filter((r) => r.from !== to && r.from !== from)\n .map((r) => (r.to === from ? { ...r, to } : r))\n .filter((r) => r.from !== r.to);\n next.push({ from, to, status: 301 });\n return next;\n}\n\n/** The redirect for a request path, if any (exact match on the normalised path). */\nexport function matchRedirect(redirects: readonly Redirect[], path: string): Redirect | undefined {\n return redirects.find((r) => r.from === path && isSafeHref(r.to));\n}\n"]}