@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.
- package/README.md +241 -13
- package/dist/assets/islands.77d11f5697.js +1 -0
- package/dist/assets/sites-forms.732cc7e0c1.css +10 -0
- package/dist/assets/sites-forms.css +1 -1
- package/dist/assets/sites.716b4ac1a5.css +2 -0
- package/dist/assets/sites.css +1 -1
- package/dist/assets.generated-QSB7EJWX.js +3 -0
- package/dist/assets.generated-QSB7EJWX.js.map +1 -0
- package/dist/blocks.d.ts +1 -1
- package/dist/blocks.js +5 -1
- package/dist/blocks.js.map +1 -1
- package/dist/chunk-3VKTBE7S.js +69 -0
- package/dist/chunk-3VKTBE7S.js.map +1 -0
- package/dist/chunk-5IXDFFEG.js +465 -0
- package/dist/chunk-5IXDFFEG.js.map +1 -0
- package/dist/chunk-C375ZPU2.js +2241 -0
- package/dist/chunk-C375ZPU2.js.map +1 -0
- package/dist/{chunk-GA7U3CIN.js → chunk-FBQF2L7O.js} +317 -97
- package/dist/chunk-FBQF2L7O.js.map +1 -0
- package/dist/chunk-H6ED3K4R.js +18 -0
- package/dist/chunk-H6ED3K4R.js.map +1 -0
- package/dist/chunk-KPOX7D4S.js +250 -0
- package/dist/chunk-KPOX7D4S.js.map +1 -0
- package/dist/chunk-VZUDRPFG.js +13 -0
- package/dist/chunk-VZUDRPFG.js.map +1 -0
- package/dist/{chunk-KEF3V5ZN.js → chunk-ZGWGQGT2.js} +169 -73
- package/dist/chunk-ZGWGQGT2.js.map +1 -0
- package/dist/editor.d.ts +526 -0
- package/dist/editor.js +2480 -0
- package/dist/editor.js.map +1 -0
- package/dist/handler-QHH453YG.js +9 -0
- package/dist/handler-QHH453YG.js.map +1 -0
- package/dist/import.d.ts +130 -0
- package/dist/import.js +330 -0
- package/dist/import.js.map +1 -0
- package/dist/index.d.ts +47 -8
- package/dist/index.js +5 -250
- package/dist/index.js.map +1 -1
- package/dist/{registry-CdgVymsu.d.ts → registry-HBn1X60x.d.ts} +274 -8
- package/dist/sections.d.ts +422 -6
- package/dist/sections.js +4 -2
- package/dist/{store-BzGw2i5J.d.ts → store-BXiZeZzH.d.ts} +119 -53
- package/dist/supabase.d.ts +5 -5
- package/dist/supabase.js +115 -6
- package/dist/supabase.js.map +1 -1
- package/dist/web.d.ts +26 -8
- package/dist/web.js +7 -353
- package/dist/web.js.map +1 -1
- package/migrations/0001_genesis_sites.sql +64 -6
- package/migrations/0002_genesis_sites_posts.sql +404 -0
- package/migrations/tests/0001_genesis_sites.test.sql +30 -1
- package/migrations/tests/0002_genesis_sites_posts.test.sql +242 -0
- package/package.json +28 -10
- package/dist/assets/islands.230b20b9c4.js +0 -1
- package/dist/assets/sites-forms.5e6ebf31c3.css +0 -10
- package/dist/assets/sites.b28b796c6f.css +0 -2
- package/dist/chunk-43XUAO63.js +0 -1255
- package/dist/chunk-43XUAO63.js.map +0 -1
- package/dist/chunk-GA7U3CIN.js.map +0 -1
- 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
|
-
/**
|
|
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
|
|
578
|
-
*
|
|
579
|
-
*
|
|
580
|
-
*
|
|
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
|
-
/**
|
|
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 {
|
|
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 };
|