@sevenfold/setto-client 0.34.0 → 0.36.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/dist/index.d.ts CHANGED
@@ -13,6 +13,10 @@ export type { SettoIconProps, SettoIconRenderProps } from './SettoIcon';
13
13
  export { SettoImage } from './SettoImage';
14
14
  export type { SettoImageProps, ImageToolsProps } from './SettoImage';
15
15
  export { SETTO_IMAGE_QUALITY, SETTO_IMAGE_WIDTHS, isOptimizable, optimizedSrcSet, optimizedUrl, settoVercelImagesConfig, } from './lib/optimized-image';
16
+ export { SETTO_MEDIA_HOST, isSettoMediaUrl } from './lib/media';
17
+ export { SettoBlog, SettoBlogSection, SettoBlogLatest, BLOG_CSS } from './blog/SettoBlog';
18
+ export { postsForLanguage, postForSlug, formatPostDate } from './blog/data';
19
+ export type { SettoBlogData, BlogPostData, BlogPostSummary } from './blog/data';
16
20
  export { SettoRepeater } from './SettoRepeater';
17
21
  export type { SettoRepeaterProps } from './SettoRepeater';
18
22
  export { SettoForm, FORM_FIELD_TYPES, FORM_FIELD_TYPE_LABELS, fieldTypeHasOptions, fieldTypeHasPlaceholder, formFieldsPrefix, isFormFieldType, readLocaleFields, settoSubmissionUrl, } from './modules/forms';
@@ -27,7 +31,7 @@ export type { SettoMapProps } from './SettoMap';
27
31
  export type { MapLocation, MapToolsProps, MapToolsComponent } from './map-tools';
28
32
  export { SettoPage, SettoTextSection, usePageManifest, useSettoMenu, } from './pages/SettoPage';
29
33
  export type { SettoPageProps, BuiltinSectionProps } from './pages/SettoPage';
30
- export { PAGES_PATH, PAGES_MANIFEST_VERSION, BUILTIN_SECTION_TYPES, parseManifest, normalisePath, pageForPath, pageById, findSection, visibleMenu, applyOp, applyOps, builtinKeys, pageTitleKey, serialiseManifest, isSafeHref, ManifestError, } from './pages/manifest';
34
+ export { PAGES_PATH, PAGES_MANIFEST_VERSION, BUILTIN_SECTION_TYPES, parseManifest, normalisePath, pageForPath, blogPage, blogSlugForPath, pageById, findSection, visibleMenu, applyOp, applyOps, builtinKeys, pageTitleKey, serialiseManifest, isSafeHref, ManifestError, } from './pages/manifest';
31
35
  export type { PagesManifest, PageEntry, PageSection, MenuItem, MenuList, ManifestOp, ManifestIssue, ManifestParse, BuiltinSectionType, } from './pages/manifest';
32
36
  export { PageStore, EMPTY_PAGE_STORE_SNAPSHOT, countChanges } from './lib/page-store';
33
37
  export type { PageStoreSnapshot } from './lib/page-store';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Setto's public media store: the `setto-media` Vercel Blob store, where blog
3
+ * photographs live instead of in each site's repo (R24). setto-server writes
4
+ * to it (`blog/<siteId>/<hash>/<name>.<ext>`), a post refers to the URL, and
5
+ * the site's Vercel Image Optimization resizes it through the
6
+ * `remotePatterns` entry in `settoVercelImagesConfig`.
7
+ *
8
+ * One store for every site, so its host is a constant. It changes only if the
9
+ * store is replaced — then here, in the server's token, and in each site's
10
+ * `vercel.json`, together.
11
+ */
12
+ export declare const SETTO_MEDIA_HOST = "3adyw42hy72dtzjo.public.blob.vercel-storage.com";
13
+ /** Where blog photographs sit in the store. */
14
+ export declare const SETTO_MEDIA_BLOG_PREFIX = "/blog/";
15
+ /** A blog photograph in Setto's media store: https, that host, under `/blog/`. */
16
+ export declare function isSettoMediaUrl(src: string | null | undefined): src is string;
@@ -8,6 +8,12 @@
8
8
  * `images` block in `vercel.json` whose `sizes` and `qualities` are exactly
9
9
  * the constants below — Vercel refuses a `w` or `q` it was not given. The
10
10
  * block, for copying: `settoVercelImagesConfig`.
11
+ *
12
+ * Blog photographs are the one exception to "a file of this site's own": they
13
+ * live in Setto's media store (`./media.ts`) and reach the optimizer through
14
+ * the block's `remotePatterns` entry. A site whose `vercel.json` predates that
15
+ * entry gets a refusal from the optimizer, and `SettoImage` falls back to the
16
+ * original, as it does for any failed variant.
11
17
  */
12
18
  /** Phone, phone at 2–3×, tablet, laptop, wide and retina desktop. */
13
19
  export declare const SETTO_IMAGE_WIDTHS: readonly [384, 640, 828, 1080, 1440, 1920, 2560];
@@ -22,12 +28,18 @@ export declare const settoVercelImagesConfig: {
22
28
  readonly pathname: "^/images/.*$";
23
29
  readonly search: "";
24
30
  }];
31
+ readonly remotePatterns: readonly [{
32
+ readonly protocol: "https";
33
+ readonly hostname: `^${string}$`;
34
+ readonly pathname: `^${string}.*$`;
35
+ }];
25
36
  readonly minimumCacheTTL: 2678400;
26
37
  };
27
38
  /**
28
39
  * Whether an image can go through the optimizer: a file of this site's own,
29
- * under `/images/`, in a format it transforms. A draft's `blob:` preview, an
30
- * external address, an SVG logo and a moving GIF cannot.
40
+ * under `/images/`, or a blog photograph in Setto's media store, in a format
41
+ * it transforms. A draft's `blob:` preview, any other external address, an
42
+ * SVG logo and a moving GIF cannot.
31
43
  */
32
44
  export declare function isOptimizable(src: string | null | undefined): src is string;
33
45
  /**
@@ -26,8 +26,14 @@ export declare const PAGES_PATH = "src/content/pages.json";
26
26
  * `text` is a heading, an optional intro and a list of paragraphs with
27
27
  * optional headings: enough for terms, privacy, an «about» page. It is what
28
28
  * lets Pixel add a «Vilkår» page in the chat instead of in a sandbox.
29
+ *
30
+ * `blog` is the blog (R24): the list of posts on its page, and a single post
31
+ * at `<page path>/<slug>` — the one page whose path has room below it. At
32
+ * most one per site, and never on the front page, which would swallow every
33
+ * address. `blog-latest` is a band of the newest posts, for the front page.
34
+ * Both read the posts the site's build bundles (`SettoConfig.blog`).
29
35
  */
30
- export declare const BUILTIN_SECTION_TYPES: readonly ["text"];
36
+ export declare const BUILTIN_SECTION_TYPES: readonly ["text", "blog", "blog-latest"];
31
37
  export type BuiltinSectionType = (typeof BUILTIN_SECTION_TYPES)[number];
32
38
  export interface PageSection {
33
39
  /** Unique across the whole site: it is also the theme id and the anchor. */
@@ -85,6 +91,17 @@ export declare function isSafeHref(href: string): boolean;
85
91
  /** `/vilkar/` and `/vilkar` are one page; the empty path is the front page. */
86
92
  export declare function normalisePath(path: string): string;
87
93
  export declare function pageForPath(manifest: PagesManifest, path: string): PageEntry | null;
94
+ /** The page holding the site's blog, and the section on it. */
95
+ export declare function blogPage(manifest: PagesManifest): {
96
+ page: PageEntry;
97
+ section: PageSection;
98
+ } | null;
99
+ /**
100
+ * The post a path names: `/blogg/ny-kaffemaskin` → `ny-kaffemaskin` when the
101
+ * blog lives at `/blogg`. One segment below the blog page and a valid slug;
102
+ * anything else is not a post.
103
+ */
104
+ export declare function blogSlugForPath(manifest: PagesManifest, path: string): string | null;
88
105
  export declare function pageById(manifest: PagesManifest, id: string): PageEntry | null;
89
106
  /** The page a section is on, and where. */
90
107
  export declare function findSection(manifest: PagesManifest, sectionId: string): {