@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
@@ -14,13 +14,51 @@ import { z } from 'zod';
14
14
 
15
15
  /** A link target: a site path, a fragment, or an http(s), mailto or tel URL. */
16
16
  declare const Href: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
17
- /** A labelled link: a button, a menu entry, a footer link. */
17
+ /** An analytics event name for a link: `data-gs-event` on the page (default `cta` on buttons). */
18
+ declare const LinkEvent: z.ZodString;
19
+ /**
20
+ * A labelled link: a button, a menu entry, a footer link, an outbound
21
+ * booking link.
22
+ *
23
+ * - `external: true` marks a link that leaves the site (a booking or
24
+ * membership system): it must be an `http(s)` URL, and it renders with
25
+ * `rel="noopener noreferrer"` and `data-gs-outbound` for analytics.
26
+ * - `target` (`_blank` for a new tab) applies to http(s) links only;
27
+ * `newTab: true` is the older spelling of `target: "_blank"`.
28
+ * - `event` names the click for the host's analytics (`data-gs-event`).
29
+ */
18
30
  declare const Link: z.ZodObject<{
19
31
  label: z.ZodString;
20
32
  href: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
21
33
  newTab: z.ZodOptional<z.ZodBoolean>;
34
+ target: z.ZodOptional<z.ZodEnum<{
35
+ _self: "_self";
36
+ _blank: "_blank";
37
+ }>>;
38
+ external: z.ZodOptional<z.ZodBoolean>;
39
+ event: z.ZodOptional<z.ZodString>;
22
40
  }, z.core.$strip>;
23
41
  type Link = z.infer<typeof Link>;
42
+ /** Does this link open in a new tab? Only an http(s) link can. */
43
+ declare const opensInNewTab: (link: Pick<Link, "href" | "newTab" | "target">) => boolean;
44
+ /**
45
+ * A downloadable file (a PDF timetable, a waiver): a site path (an upload
46
+ * under `sites/<site_id>/files/`) or an https URL. `bytes` and `mime` say
47
+ * what the visitor is about to download.
48
+ */
49
+ declare const FileRef: z.ZodObject<{
50
+ src: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
51
+ mime: z.ZodDefault<z.ZodEnum<{
52
+ "application/pdf": "application/pdf";
53
+ "image/png": "image/png";
54
+ "image/jpeg": "image/jpeg";
55
+ "image/webp": "image/webp";
56
+ "image/avif": "image/avif";
57
+ "image/gif": "image/gif";
58
+ }>>;
59
+ bytes: z.ZodOptional<z.ZodNumber>;
60
+ }, z.core.$strip>;
61
+ type FileRef = z.infer<typeof FileRef>;
24
62
  /**
25
63
  * An image. `alt` describes it for someone who can't see it; an image that
26
64
  * adds nothing (a texture) is `decorative: true` and gets an empty alt. The
@@ -134,9 +172,16 @@ declare const PageDoc: z.ZodObject<{
134
172
  }, z.core.$strip>>;
135
173
  }, z.core.$strip>;
136
174
  type PageDoc = z.infer<typeof PageDoc>;
175
+ /**
176
+ * What a page is: an ordinary `page`, a focused `landing` page, or the
177
+ * `post` page: the template every blog post renders in. A site has at most
178
+ * one post page; at its own path (`/blog`) it is the blog's index, and at
179
+ * `/blog/<slug>` it shows that post in its `post-body` section.
180
+ */
137
181
  declare const PageKind: z.ZodEnum<{
138
182
  page: "page";
139
183
  landing: "landing";
184
+ post: "post";
140
185
  }>;
141
186
  type PageKind = z.infer<typeof PageKind>;
142
187
  declare const PagePath: z.ZodString;
@@ -340,6 +385,7 @@ declare const ReleasePage: z.ZodObject<{
340
385
  kind: z.ZodEnum<{
341
386
  page: "page";
342
387
  landing: "landing";
388
+ post: "post";
343
389
  }>;
344
390
  doc: z.ZodObject<{
345
391
  schemaVersion: z.ZodLiteral<1>;
@@ -494,6 +540,7 @@ declare const ReleaseSnapshot: z.ZodObject<{
494
540
  kind: z.ZodEnum<{
495
541
  page: "page";
496
542
  landing: "landing";
543
+ post: "post";
497
544
  }>;
498
545
  doc: z.ZodObject<{
499
546
  schemaVersion: z.ZodLiteral<1>;
@@ -574,10 +621,15 @@ declare const MAX_DOC_BYTES: number;
574
621
  * form by its slug; the host says what that slug is, through a resolver
575
622
  * passed to the renderer. This package assumes no forms table.
576
623
  *
577
- * - `definition`: a genesis-forms definition. The page renders it on the
578
- * server with forms-web's `<Form>`, and the form island makes it
579
- * interactive; answers are POSTed as JSON to `submitUrl` (the host's
580
- * endpoint, for example one that runs genesis-forms destinations).
624
+ * - `definition`: a genesis-forms definition, sent to an endpoint. The page
625
+ * renders it on the server (a plain HTML form when it needs no engine,
626
+ * forms-web's `<Form>` and the form island otherwise), and answers are
627
+ * POSTed as JSON (`{ form, answers }`) to `submitUrl`: a site path (the
628
+ * host's own endpoint, for example one that runs genesis-forms
629
+ * destinations) or an https URL (another service's endpoint).
630
+ * - `mailto`: no form at all, a button that opens the visitor's email to
631
+ * `email`. The fallback for a site with no endpoint yet: nothing is
632
+ * stored, and a page never posts a form to `mailto:`.
581
633
  * - `embed`: an https URL the page shows in an iframe (a hosted form).
582
634
  */
583
635
  type ResolvedForm = {
@@ -588,6 +640,16 @@ type ResolvedForm = {
588
640
  submitUrl: string;
589
641
  layout?: "classic" | "focus";
590
642
  submitLabel?: string;
643
+ } | {
644
+ kind: "mailto";
645
+ /** The address the button writes to. */
646
+ email: string;
647
+ /** The email's subject line. */
648
+ subject?: string;
649
+ /** The button's label (default "Email us"). */
650
+ label?: string;
651
+ /** A line above the button. */
652
+ note?: string;
591
653
  } | {
592
654
  kind: "embed";
593
655
  /** An https URL. */
@@ -604,6 +666,188 @@ interface FormsResolverContext {
604
666
  }
605
667
  /** slug → the form to show, or null when the host has no such form (the section then renders nothing and logs). */
606
668
  type FormsResolver = (slug: string, ctx: FormsResolverContext) => ResolvedForm | null | Promise<ResolvedForm | null>;
669
+ /** A plain email address (no display name, no `%` escapes, no header injection): what a `mailto` form may write to. */
670
+ declare function isPlainEmail(value: unknown): value is string;
671
+ /** The `mailto:` link for a mailto form, or null when its address isn't a plain one. */
672
+ declare function mailtoHref(form: Extract<ResolvedForm, {
673
+ kind: "mailto";
674
+ }>): string | null;
675
+
676
+ /**
677
+ * Blog posts: a site's collection of dated articles.
678
+ *
679
+ * A post is its own document (`PostDoc`), kept beside the pages rather than
680
+ * in them, with a draft and a published copy. `publishPost` checks the draft
681
+ * and copies it to the published copy; that copy is what visitors see, so
682
+ * a post goes live (and comes down) on its own, without republishing the
683
+ * site. The site's `post` page is the template every post renders in: at its
684
+ * own path it is the blog's index, and at `<path>/<slug>` it shows the post.
685
+ */
686
+
687
+ /** A post's slug: lowercase letters, digits and single hyphens (`september-testing`). */
688
+ declare const PostSlug: z.ZodString;
689
+ declare const PostAuthor: z.ZodObject<{
690
+ name: z.ZodString;
691
+ url: z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
692
+ }, z.core.$strip>;
693
+ declare const PostDoc: z.ZodObject<{
694
+ schemaVersion: z.ZodLiteral<1>;
695
+ title: z.ZodString;
696
+ excerpt: z.ZodOptional<z.ZodString>;
697
+ body: z.ZodObject<{
698
+ type: z.ZodLiteral<"doc">;
699
+ content: z.ZodOptional<z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
700
+ }, z.core.$strip>;
701
+ cover: z.ZodOptional<z.ZodObject<{
702
+ src: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
703
+ alt: z.ZodDefault<z.ZodString>;
704
+ decorative: z.ZodOptional<z.ZodBoolean>;
705
+ width: z.ZodOptional<z.ZodNumber>;
706
+ height: z.ZodOptional<z.ZodNumber>;
707
+ focal: z.ZodOptional<z.ZodObject<{
708
+ x: z.ZodNumber;
709
+ y: z.ZodNumber;
710
+ }, z.core.$strip>>;
711
+ }, z.core.$strip>>;
712
+ author: z.ZodOptional<z.ZodObject<{
713
+ name: z.ZodString;
714
+ url: z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
715
+ }, z.core.$strip>>;
716
+ category: z.ZodOptional<z.ZodString>;
717
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
718
+ seo: z.ZodOptional<z.ZodObject<{
719
+ title: z.ZodOptional<z.ZodString>;
720
+ description: z.ZodOptional<z.ZodString>;
721
+ ogImage: z.ZodOptional<z.ZodObject<{
722
+ src: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
723
+ alt: z.ZodDefault<z.ZodString>;
724
+ decorative: z.ZodOptional<z.ZodBoolean>;
725
+ width: z.ZodOptional<z.ZodNumber>;
726
+ height: z.ZodOptional<z.ZodNumber>;
727
+ focal: z.ZodOptional<z.ZodObject<{
728
+ x: z.ZodNumber;
729
+ y: z.ZodNumber;
730
+ }, z.core.$strip>>;
731
+ }, z.core.$strip>>;
732
+ canonical: z.ZodOptional<z.ZodURL>;
733
+ noindex: z.ZodOptional<z.ZodBoolean>;
734
+ }, z.core.$strip>>;
735
+ }, z.core.$strip>;
736
+ type PostDoc = z.infer<typeof PostDoc>;
737
+ type PostDocInput = z.input<typeof PostDoc>;
738
+ type PostStatus = "draft" | "published";
739
+ /** A post as the editor lists it. */
740
+ interface PostMeta {
741
+ id: string;
742
+ siteId: string;
743
+ slug: string;
744
+ title: string;
745
+ status: PostStatus;
746
+ /** The draft's revision, for compare-and-swap saves. */
747
+ rev: number;
748
+ /** When it was first published (kept when it is published again), or null. */
749
+ publishedAt: string | null;
750
+ updatedAt: string;
751
+ }
752
+ /** A post's draft, for the editor. */
753
+ interface PostDraft extends PostMeta {
754
+ doc: PostDoc;
755
+ }
756
+ /** A published post, as visitors see it. */
757
+ interface LivePost {
758
+ slug: string;
759
+ publishedAt: string;
760
+ /** When its published copy last changed. */
761
+ updatedAt: string;
762
+ doc: PostDoc;
763
+ }
764
+ /** A published post in a list: everything but the body. */
765
+ interface PostSummary {
766
+ slug: string;
767
+ title: string;
768
+ excerpt?: string;
769
+ cover?: Image;
770
+ author?: z.infer<typeof PostAuthor>;
771
+ category?: string;
772
+ /** Kept out of the sitemap and the feed (`seo.noindex`, or a canonical elsewhere). */
773
+ noindex?: boolean;
774
+ publishedAt: string;
775
+ updatedAt: string;
776
+ }
777
+ /** A list item as a store returns it, checked: a stored row that skipped the checks is left out. */
778
+ declare const PostSummarySchema: z.ZodObject<{
779
+ slug: z.ZodString;
780
+ title: z.ZodString;
781
+ excerpt: z.ZodOptional<z.ZodString>;
782
+ cover: z.ZodOptional<z.ZodObject<{
783
+ src: z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>;
784
+ alt: z.ZodDefault<z.ZodString>;
785
+ decorative: z.ZodOptional<z.ZodBoolean>;
786
+ width: z.ZodOptional<z.ZodNumber>;
787
+ height: z.ZodOptional<z.ZodNumber>;
788
+ focal: z.ZodOptional<z.ZodObject<{
789
+ x: z.ZodNumber;
790
+ y: z.ZodNumber;
791
+ }, z.core.$strip>>;
792
+ }, z.core.$strip>>;
793
+ author: z.ZodOptional<z.ZodObject<{
794
+ name: z.ZodString;
795
+ url: z.ZodOptional<z.ZodString & z.ZodType<string, string, z.core.$ZodTypeInternals<string, string>>>;
796
+ }, z.core.$strip>>;
797
+ category: z.ZodOptional<z.ZodString>;
798
+ noindex: z.ZodOptional<z.ZodBoolean>;
799
+ publishedAt: z.ZodString;
800
+ updatedAt: z.ZodString;
801
+ }, z.core.$strip>;
802
+ /** The most posts a list reads (the newest first). */
803
+ declare const MAX_LIVE_POSTS = 500;
804
+ /** A save of a post: a new one (no `id`), or a compare-and-swap of an existing one's draft. */
805
+ interface SavePostInput {
806
+ id?: string;
807
+ slug: string;
808
+ /** The draft revision this save started from (required with `id`). */
809
+ rev?: number;
810
+ doc: PostDocInput;
811
+ }
812
+ type SavePostResult = {
813
+ id: string;
814
+ rev: number;
815
+ } | {
816
+ id: string;
817
+ conflict: PostDoc;
818
+ rev: number;
819
+ };
820
+ /** One post to import (a move from another site): published as of `publishedAt` unless it fails a check. */
821
+ interface ImportPost {
822
+ slug: string;
823
+ doc: PostDocInput;
824
+ /** When it was first published, kept from the old site (default: now). */
825
+ publishedAt?: string;
826
+ /** `draft` imports it unpublished. Default `published`. */
827
+ status?: PostStatus;
828
+ }
829
+ interface ImportPostsResult {
830
+ /** Imported posts: published, or a draft when asked for or when a check failed (see `issues`). */
831
+ imported: {
832
+ slug: string;
833
+ id: string;
834
+ status: PostStatus;
835
+ issues?: string[];
836
+ }[];
837
+ /** Posts left out: a slug the site already has, or a document that doesn't parse. */
838
+ skipped: {
839
+ slug: string;
840
+ reason: string;
841
+ }[];
842
+ }
843
+ /** The most posts one `importPosts` call takes. */
844
+ declare const MAX_IMPORT_POSTS = 500;
845
+ /** A published post as a list item. */
846
+ declare function postSummary(post: LivePost): PostSummary;
847
+ /** Plain text of a rich text document (for a feed's description when a post has no excerpt). */
848
+ declare function richTextPlain(value: unknown, max?: number): string;
849
+ /** Validate a post slug, throwing with a readable message. */
850
+ declare function validatePostSlug(slug: string): string;
607
851
 
608
852
  /**
609
853
  * Sections: `defineSection` describes one kind of section (its props schema,
@@ -660,6 +904,20 @@ interface RenderContext {
660
904
  mode: "live" | "preview";
661
905
  /** A prefix that makes ids unique on the page: the section node's id. */
662
906
  idPrefix: string;
907
+ /**
908
+ * The site's blog, when it has a post page: its path, the published posts
909
+ * (newest first, without bodies), the post this page shows (on
910
+ * `<path>/<slug>`), and the list's page number (`?page=`).
911
+ */
912
+ posts?: PostsContext;
913
+ }
914
+ interface PostsContext {
915
+ /** The post page's path (`/blog`): posts live at `<path>/<slug>`. */
916
+ path: string;
917
+ list: readonly PostSummary[];
918
+ current: LivePost | null;
919
+ /** The list's page, from `?page=` (1 when absent). */
920
+ page: number;
663
921
  }
664
922
  interface SectionRenderProps<P> {
665
923
  props: P;
@@ -694,7 +952,15 @@ interface SectionDefinition<P = Record<string, unknown>> {
694
952
  * the renderer, and a publish writes the result into the release.
695
953
  */
696
954
  migrations?: Readonly<Record<number, (props: Record<string, unknown>) => Record<string, unknown>>>;
697
- /** Server-safe React: no state, no effects, no browser APIs. */
955
+ /**
956
+ * The https origins this section frames (a map), so the page's
957
+ * Content-Security-Policy allows them in `frame-src`. Only origins the
958
+ * section builds itself, never a URL an editor typed.
959
+ */
960
+ frameOrigins?: (props: P) => readonly string[];
961
+ /** It needs the islands loader (a click-to-load map, say). */
962
+ islands?: boolean;
963
+ /** Server-safe React: no state, no effects, no browser APIs. Returning null gives the page's h1 back. */
698
964
  render: (input: SectionRenderProps<P>) => ReactNode;
699
965
  }
700
966
  /** A definition as the registry holds it: props erased to a record. */
@@ -711,7 +977,7 @@ declare class SectionDefinitionError extends Error {
711
977
  */
712
978
  declare function defineSection<P>(def: SectionDefinition<P>): Readonly<SectionDefinition<P>>;
713
979
  /** The built-in section kinds, which a host replaces only with `{ replace: true }`. */
714
- declare const BUILT_IN_SECTION_TYPES: readonly ["nav", "hero", "features", "cta", "testimonials", "faq", "pricing", "logos", "stats", "gallery", "rich-text", "form-embed", "footer"];
980
+ declare const BUILT_IN_SECTION_TYPES: readonly ["nav", "hero", "features", "cta", "testimonials", "faq", "pricing", "logos", "stats", "gallery", "rich-text", "form-embed", "footer", "schedule", "team", "blog-list", "post-body", "map", "timeline", "file"];
715
981
  type BuiltInSectionType = (typeof BUILT_IN_SECTION_TYPES)[number];
716
982
  interface RegisterSectionOptions {
717
983
  /** Replace a built-in kind, for every site in this process. */
@@ -761,4 +1027,4 @@ declare function newSectionId(prefix?: string): string;
761
1027
  /** A section node from a preset: the editor's Add, and templates. */
762
1028
  declare function nodeFromPreset(type: string, presetName?: string, id?: string): SectionNode;
763
1029
 
764
- export { unregisterSection as $, type AnySectionDefinition as A, BUILT_IN_SECTION_TYPES as B, Copy as C, type SectionRenderProps as D, type SectionVariant as E, FontChoice as F, Seo as G, Href as H, Image as I, SeoDefaults as J, Surface as K, Link as L, MAX_DOC_BYTES as M, defineSection as N, getSection as O, PageDoc as P, listSections as Q, ReleasePage as R, SectionNode as S, TokenOverrides as T, newSectionId as U, nodeFromPreset as V, parseSnapshot as W, registerBuiltInSection as X, registerSection as Y, sectionJsonSchema as Z, sectionManifests as _, SiteDoc as a, Redirect as b, type SiteDocInput as c, PageKind as d, type BuiltInSectionType as e, type FormsResolver as f, type FormsResolverContext as g, Line as h, MenuItem as i, type PageMeta as j, PagePath as k, type RegisterSectionOptions as l, type Release as m, type ReleaseMeta as n, ReleaseSnapshot as o, type RenderContext as p, type ResolvedForm as q, RichText as r, SECTION_CATEGORIES as s, type SectionCategory as t, type SectionDefinition as u, SectionDefinitionError as v, SectionId as w, type SectionManifest as x, type SectionPlacement as y, type SectionPreset as z };
1030
+ export { SectionId as $, type AnySectionDefinition as A, BUILT_IN_SECTION_TYPES as B, Copy as C, type PostDocInput as D, type PostDraft as E, type FormsResolver as F, type PostMeta as G, Href as H, Image as I, PostSlug as J, type PostStatus as K, type LivePost as L, MAX_DOC_BYTES as M, PostSummarySchema as N, type PostsContext as O, PageKind as P, type RegisterSectionOptions as Q, type Release as R, type SectionCategory as S, type ReleaseMeta as T, ReleaseSnapshot as U, RichText as V, SECTION_CATEGORIES as W, type SavePostInput as X, type SavePostResult as Y, type SectionDefinition as Z, SectionDefinitionError as _, PageDoc as a, type SectionManifest as a0, type SectionPlacement as a1, type SectionPreset as a2, type SectionRenderProps as a3, type SectionVariant as a4, SeoDefaults as a5, Surface as a6, TokenOverrides as a7, defineSection as a8, getSection as a9, isPlainEmail as aa, listSections as ab, mailtoHref as ac, newSectionId as ad, nodeFromPreset as ae, opensInNewTab as af, parseSnapshot as ag, postSummary as ah, registerBuiltInSection as ai, registerSection as aj, richTextPlain as ak, sectionJsonSchema as al, sectionManifests as am, unregisterSection as an, validatePostSlug as ao, type PageMeta as b, type RenderContext as c, type ResolvedForm as d, Seo as e, SectionNode as f, SiteDoc as g, ReleasePage as h, type PostSummary as i, Redirect as j, Link as k, type SiteDocInput as l, type BuiltInSectionType as m, FileRef as n, FontChoice as o, type FormsResolverContext as p, type ImportPost as q, type ImportPostsResult as r, Line as s, LinkEvent as t, MAX_IMPORT_POSTS as u, MAX_LIVE_POSTS as v, MenuItem as w, PagePath as x, PostAuthor as y, PostDoc as z };