@sevenfold/setto-client 0.36.1 → 0.37.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/blog/SettoBlog.d.ts +46 -0
- package/dist/index.d.ts +3 -2
- package/dist/pages/SettoPage.d.ts +7 -1
- package/dist/pages/manifest.d.ts +12 -0
- package/dist/setto-client.js +120 -38
- package/dist/setto-client.js.map +1 -1
- package/dist/vite.js.map +1 -1
- package/package.json +1 -1
package/dist/blog/SettoBlog.d.ts
CHANGED
|
@@ -1,4 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The blog's two built-in sections (R24).
|
|
3
|
+
*
|
|
4
|
+
* `blog` lives on the blog page and draws either the list of posts or, at
|
|
5
|
+
* `<page path>/<slug>`, one post. `blog-latest` is a band of the newest posts
|
|
6
|
+
* for the front page. Both read the posts the site's build bundles
|
|
7
|
+
* (`SettoConfig.blog`, from `virtual:setto-blog`). The band draws nothing
|
|
8
|
+
* without them; the blog page says there are none yet.
|
|
9
|
+
*
|
|
10
|
+
* The owner, signed in on their own site, also gets the `blog-owner` chrome
|
|
11
|
+
* slot at the top of the blog page: Pixel's welcome on an empty blog, the
|
|
12
|
+
* article Pixel is writing, and a draft waiting for approval — drawn here, in
|
|
13
|
+
* the site's own blog design, by `BlogDraft`, so what the owner approves is
|
|
14
|
+
* what readers will see.
|
|
15
|
+
*
|
|
16
|
+
* The look is the site's: type and colour are inherited, and the stylesheet
|
|
17
|
+
* below only gives shape — scoped under `.setto-blog` so Tailwind's reset
|
|
18
|
+
* cannot strip it, and at zero specificity for colour so the site always
|
|
19
|
+
* wins. However a redesign restyles these classes, the posts keep rendering:
|
|
20
|
+
* the file contract is what may not change.
|
|
21
|
+
*/
|
|
22
|
+
import { type ComponentType } from 'react';
|
|
23
|
+
import type { RootContent } from 'mdast';
|
|
1
24
|
import { type BuiltinSectionProps } from '../pages/SettoPage.js';
|
|
25
|
+
import { type BlogFrontmatter } from './contract.js';
|
|
2
26
|
export declare function SettoBlogSection({ sectionId, first }: BuiltinSectionProps): import("react/jsx-runtime").JSX.Element;
|
|
3
27
|
/**
|
|
4
28
|
* The blog for a site that routes by hand instead of through `pages.json`
|
|
@@ -11,6 +35,28 @@ export declare function SettoBlog({ basePath, title }: {
|
|
|
11
35
|
basePath?: string;
|
|
12
36
|
title?: string;
|
|
13
37
|
}): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
/** A post not yet published, as setto-server sends it: the frontmatter and the body's tree, each node with `at`. */
|
|
39
|
+
export interface BlogDraftData {
|
|
40
|
+
frontmatter: BlogFrontmatter;
|
|
41
|
+
body: {
|
|
42
|
+
children: RootContent[];
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/** What the chrome's `blog-owner` slot is given. */
|
|
46
|
+
export interface BlogOwnerSlotProps {
|
|
47
|
+
blogPath: string;
|
|
48
|
+
language: string;
|
|
49
|
+
/** Published posts in this language, as of the site's last build. */
|
|
50
|
+
posts: number;
|
|
51
|
+
/** Draws a draft in the site's own blog design; title, lead and cover carry `data-setto-field`. */
|
|
52
|
+
Draft: ComponentType<{
|
|
53
|
+
draft: BlogDraftData;
|
|
54
|
+
}>;
|
|
55
|
+
}
|
|
56
|
+
/** A draft, as it will read once published. Given to the chrome's `blog-owner` slot. */
|
|
57
|
+
export declare function BlogDraft({ draft }: {
|
|
58
|
+
draft: BlogDraftData;
|
|
59
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
14
60
|
export declare function SettoBlogLatest({ sectionId, first }: BuiltinSectionProps): import("react/jsx-runtime").JSX.Element | null;
|
|
15
61
|
/**
|
|
16
62
|
* Shape is scoped `.setto-blog :where(…)` (one class: beats Preflight's
|
package/dist/index.d.ts
CHANGED
|
@@ -14,7 +14,8 @@ export { SettoImage } from './SettoImage.js';
|
|
|
14
14
|
export type { SettoImageProps, ImageToolsProps } from './SettoImage.js';
|
|
15
15
|
export { SETTO_IMAGE_QUALITY, SETTO_IMAGE_WIDTHS, isOptimizable, optimizedSrcSet, optimizedUrl, settoVercelImagesConfig, } from './lib/optimized-image.js';
|
|
16
16
|
export { SETTO_MEDIA_HOST, isSettoMediaUrl } from './lib/media.js';
|
|
17
|
-
export { SettoBlog, SettoBlogSection, SettoBlogLatest, BLOG_CSS } from './blog/SettoBlog.js';
|
|
17
|
+
export { SettoBlog, SettoBlogSection, SettoBlogLatest, BlogDraft, BLOG_CSS } from './blog/SettoBlog.js';
|
|
18
|
+
export type { BlogDraftData, BlogOwnerSlotProps } from './blog/SettoBlog.js';
|
|
18
19
|
export { postsForLanguage, postForSlug, formatPostDate } from './blog/data.js';
|
|
19
20
|
export type { SettoBlogData, BlogPostData, BlogPostSummary } from './blog/data.js';
|
|
20
21
|
export { SettoRepeater } from './SettoRepeater.js';
|
|
@@ -31,7 +32,7 @@ export type { SettoMapProps } from './SettoMap.js';
|
|
|
31
32
|
export type { MapLocation, MapToolsProps, MapToolsComponent } from './map-tools.js';
|
|
32
33
|
export { SettoPage, SettoTextSection, usePageManifest, useSettoMenu, } from './pages/SettoPage.js';
|
|
33
34
|
export type { SettoPageProps, BuiltinSectionProps } from './pages/SettoPage.js';
|
|
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.js';
|
|
35
|
+
export { PAGES_PATH, PAGES_MANIFEST_VERSION, BUILTIN_SECTION_TYPES, parseManifest, normalisePath, pageForPath, blogPage, blogSlugForPath, pageById, findSection, visibleMenu, ownerMenu, applyOp, applyOps, builtinKeys, pageTitleKey, serialiseManifest, isSafeHref, ManifestError, } from './pages/manifest.js';
|
|
35
36
|
export type { PagesManifest, PageEntry, PageSection, MenuItem, MenuList, ManifestOp, ManifestIssue, ManifestParse, BuiltinSectionType, } from './pages/manifest.js';
|
|
36
37
|
export { PageStore, EMPTY_PAGE_STORE_SNAPSHOT, countChanges } from './lib/page-store.js';
|
|
37
38
|
export type { PageStoreSnapshot } from './lib/page-store.js';
|
|
@@ -11,8 +11,14 @@ export declare function usePageManifest(): PagesManifest | null;
|
|
|
11
11
|
*
|
|
12
12
|
* Already filtered: hidden links, links to hidden pages and anchors to hidden
|
|
13
13
|
* sections are gone. Render each label with `<T k={item.labelKey} />`.
|
|
14
|
+
*
|
|
15
|
+
* The signed-in owner also gets the blog's link while the blog has no posts
|
|
16
|
+
* (`ownerMenu`), marked `dimmed` and drawn faded by a stylesheet this hook
|
|
17
|
+
* adds, so no site's navbar has to know about it.
|
|
14
18
|
*/
|
|
15
|
-
export declare function useSettoMenu(list?: MenuList): MenuItem
|
|
19
|
+
export declare function useSettoMenu(list?: MenuList): Array<MenuItem & {
|
|
20
|
+
dimmed?: true;
|
|
21
|
+
}> | null;
|
|
16
22
|
/** What a built-in section's renderer is given. */
|
|
17
23
|
export interface BuiltinSectionProps {
|
|
18
24
|
sectionId: string;
|
package/dist/pages/manifest.d.ts
CHANGED
|
@@ -117,6 +117,18 @@ export declare function findSection(manifest: PagesManifest, sectionId: string):
|
|
|
117
117
|
* winter should not leave a menu entry that scrolls to nothing.
|
|
118
118
|
*/
|
|
119
119
|
export declare function visibleMenu(manifest: PagesManifest, list: MenuList): MenuItem[];
|
|
120
|
+
/**
|
|
121
|
+
* The links the site's owner sees, signed in on their own site.
|
|
122
|
+
*
|
|
123
|
+
* What a visitor sees, and one more: the blog's link while the blog is on but
|
|
124
|
+
* has no posts yet. Visitors are spared a menu entry that leads to an empty
|
|
125
|
+
* page; the owner gets it `dimmed`, as the way in — the empty blog is where
|
|
126
|
+
* Pixel offers to write the first article. A blog link the owner hid
|
|
127
|
+
* themselves once posts exist stays hidden.
|
|
128
|
+
*/
|
|
129
|
+
export declare function ownerMenu(manifest: PagesManifest, list: MenuList, blogEmpty: boolean): Array<MenuItem & {
|
|
130
|
+
dimmed?: true;
|
|
131
|
+
}>;
|
|
120
132
|
export declare class ManifestError extends Error {
|
|
121
133
|
readonly code: 'page_not_found' | 'section_not_found' | 'item_not_found' | 'duplicate_id' | 'duplicate_path' | 'invalid';
|
|
122
134
|
constructor(code: 'page_not_found' | 'section_not_found' | 'item_not_found' | 'duplicate_id' | 'duplicate_path' | 'invalid', message: string);
|
package/dist/setto-client.js
CHANGED
|
@@ -21481,28 +21481,28 @@ function parseManifest(input) {
|
|
|
21481
21481
|
const rawPages = Array.isArray(input.pages) ? input.pages : null;
|
|
21482
21482
|
if (!rawPages) issues.push({ at: "pages", message: "must be a list" });
|
|
21483
21483
|
(rawPages ?? []).forEach((raw, i) => {
|
|
21484
|
-
const
|
|
21484
|
+
const at2 = `pages[${i}]`;
|
|
21485
21485
|
if (!isRecord$1(raw)) {
|
|
21486
|
-
issues.push({ at, message: "not an object" });
|
|
21486
|
+
issues.push({ at: at2, message: "not an object" });
|
|
21487
21487
|
return;
|
|
21488
21488
|
}
|
|
21489
21489
|
const id = String(raw.id ?? "");
|
|
21490
21490
|
const path2 = String(raw.path ?? "");
|
|
21491
21491
|
const titleKey = String(raw.titleKey ?? "");
|
|
21492
|
-
if (!ID.test(id)) issues.push({ at: `${
|
|
21493
|
-
else if (pageIds.has(id)) issues.push({ at: `${
|
|
21492
|
+
if (!ID.test(id)) issues.push({ at: `${at2}.id`, message: `invalid id "${id}"` });
|
|
21493
|
+
else if (pageIds.has(id)) issues.push({ at: `${at2}.id`, message: `duplicate page "${id}"` });
|
|
21494
21494
|
pageIds.add(id);
|
|
21495
|
-
if (!PATH.test(path2)) issues.push({ at: `${
|
|
21495
|
+
if (!PATH.test(path2)) issues.push({ at: `${at2}.path`, message: `invalid path "${path2}"` });
|
|
21496
21496
|
else if (path2 === "/setto" || path2.startsWith("/setto/")) {
|
|
21497
|
-
issues.push({ at: `${
|
|
21498
|
-
} else if (paths.has(path2)) issues.push({ at: `${
|
|
21497
|
+
issues.push({ at: `${at2}.path`, message: "/setto belongs to the editor" });
|
|
21498
|
+
} else if (paths.has(path2)) issues.push({ at: `${at2}.path`, message: `duplicate path "${path2}"` });
|
|
21499
21499
|
paths.add(path2);
|
|
21500
|
-
if (!titleKey) issues.push({ at: `${
|
|
21500
|
+
if (!titleKey) issues.push({ at: `${at2}.titleKey`, message: "required" });
|
|
21501
21501
|
const sections = [];
|
|
21502
21502
|
const rawSections = Array.isArray(raw.sections) ? raw.sections : null;
|
|
21503
|
-
if (!rawSections) issues.push({ at: `${
|
|
21503
|
+
if (!rawSections) issues.push({ at: `${at2}.sections`, message: "must be a list" });
|
|
21504
21504
|
(rawSections ?? []).forEach((s, j) => {
|
|
21505
|
-
const sat = `${
|
|
21505
|
+
const sat = `${at2}.sections[${j}]`;
|
|
21506
21506
|
if (!isRecord$1(s)) {
|
|
21507
21507
|
issues.push({ at: sat, message: "not an object" });
|
|
21508
21508
|
return;
|
|
@@ -21544,16 +21544,16 @@ function parseManifest(input) {
|
|
|
21544
21544
|
if (issues.length > 0) return { ok: false, issues };
|
|
21545
21545
|
return { ok: true, manifest: { version: PAGES_MANIFEST_VERSION, pages, menu, footer: footer2 } };
|
|
21546
21546
|
}
|
|
21547
|
-
function parseMenu(raw,
|
|
21547
|
+
function parseMenu(raw, at2, issues) {
|
|
21548
21548
|
if (raw === void 0) return [];
|
|
21549
21549
|
if (!Array.isArray(raw)) {
|
|
21550
|
-
issues.push({ at, message: "must be a list" });
|
|
21550
|
+
issues.push({ at: at2, message: "must be a list" });
|
|
21551
21551
|
return [];
|
|
21552
21552
|
}
|
|
21553
21553
|
const ids = /* @__PURE__ */ new Set();
|
|
21554
21554
|
const items = [];
|
|
21555
21555
|
raw.forEach((item, i) => {
|
|
21556
|
-
const iat = `${
|
|
21556
|
+
const iat = `${at2}[${i}]`;
|
|
21557
21557
|
if (!isRecord$1(item)) {
|
|
21558
21558
|
issues.push({ at: iat, message: "not an object" });
|
|
21559
21559
|
return;
|
|
@@ -21613,6 +21613,15 @@ function findSection(manifest, sectionId) {
|
|
|
21613
21613
|
function visibleMenu(manifest, list2) {
|
|
21614
21614
|
return manifest[list2].filter((item) => !item.hidden && !leadsNowhere(manifest, item.href));
|
|
21615
21615
|
}
|
|
21616
|
+
function ownerMenu(manifest, list2, blogEmpty) {
|
|
21617
|
+
const blog = blogPage(manifest);
|
|
21618
|
+
const waiting = blogEmpty && blog && !blog.page.hidden && !blog.section.hidden ? normalisePath(blog.page.path) : null;
|
|
21619
|
+
return manifest[list2].flatMap((item) => {
|
|
21620
|
+
if (!item.hidden && !leadsNowhere(manifest, item.href)) return [item];
|
|
21621
|
+
if (waiting && item.hidden && normalisePath(item.href) === waiting) return [{ ...item, dimmed: true }];
|
|
21622
|
+
return [];
|
|
21623
|
+
});
|
|
21624
|
+
}
|
|
21616
21625
|
function leadsNowhere(manifest, href) {
|
|
21617
21626
|
if (!href.startsWith("/") && !href.startsWith("#")) return false;
|
|
21618
21627
|
const [pathPart, fragment] = href.split("#");
|
|
@@ -21656,8 +21665,8 @@ function placeSection(manifest, sectionId, index2) {
|
|
|
21656
21665
|
const found = findSection(next, sectionId);
|
|
21657
21666
|
if (!found) throw new ManifestError("section_not_found", `no section "${sectionId}"`);
|
|
21658
21667
|
const [moved] = found.page.sections.splice(found.index, 1);
|
|
21659
|
-
const
|
|
21660
|
-
found.page.sections.splice(
|
|
21668
|
+
const at2 = Math.max(0, Math.min(index2, found.page.sections.length));
|
|
21669
|
+
found.page.sections.splice(at2, 0, moved);
|
|
21661
21670
|
return next;
|
|
21662
21671
|
}
|
|
21663
21672
|
function setSectionHidden(manifest, sectionId, hidden) {
|
|
@@ -21675,8 +21684,8 @@ function addSection(manifest, pageId, section, index2) {
|
|
|
21675
21684
|
}
|
|
21676
21685
|
const next = clone(manifest);
|
|
21677
21686
|
const page = mustPage(next, pageId);
|
|
21678
|
-
const
|
|
21679
|
-
page.sections.splice(
|
|
21687
|
+
const at2 = index2 === void 0 ? page.sections.length : Math.max(0, Math.min(index2, page.sections.length));
|
|
21688
|
+
page.sections.splice(at2, 0, { ...section });
|
|
21680
21689
|
return next;
|
|
21681
21690
|
}
|
|
21682
21691
|
function addPage(manifest, page) {
|
|
@@ -34621,19 +34630,19 @@ class EditMap {
|
|
|
34621
34630
|
this.index.clear();
|
|
34622
34631
|
}
|
|
34623
34632
|
}
|
|
34624
|
-
function addImplementation(editMap,
|
|
34633
|
+
function addImplementation(editMap, at2, remove2, add) {
|
|
34625
34634
|
if (remove2 === 0 && add.length === 0) {
|
|
34626
34635
|
return;
|
|
34627
34636
|
}
|
|
34628
|
-
const existing = editMap.index.get(
|
|
34637
|
+
const existing = editMap.index.get(at2);
|
|
34629
34638
|
if (existing) {
|
|
34630
34639
|
existing[1] += remove2;
|
|
34631
34640
|
existing[2].push(...add);
|
|
34632
34641
|
return;
|
|
34633
34642
|
}
|
|
34634
|
-
const change = [
|
|
34643
|
+
const change = [at2, remove2, add];
|
|
34635
34644
|
editMap.map.push(change);
|
|
34636
|
-
editMap.index.set(
|
|
34645
|
+
editMap.index.set(at2, change);
|
|
34637
34646
|
}
|
|
34638
34647
|
function gfmTableAlign(events, index2) {
|
|
34639
34648
|
let inDelimiterRow = false;
|
|
@@ -35213,11 +35222,11 @@ function createTypingSender(send, now = Date.now) {
|
|
|
35213
35222
|
stop();
|
|
35214
35223
|
return;
|
|
35215
35224
|
}
|
|
35216
|
-
const
|
|
35217
|
-
if (typing &&
|
|
35225
|
+
const at2 = now();
|
|
35226
|
+
if (typing && at2 - lastSentAt < TYPING_THROTTLE_MS) return;
|
|
35218
35227
|
if (send(true)) {
|
|
35219
35228
|
typing = true;
|
|
35220
|
-
lastSentAt =
|
|
35229
|
+
lastSentAt = at2;
|
|
35221
35230
|
}
|
|
35222
35231
|
}
|
|
35223
35232
|
return { update, stop, reset };
|
|
@@ -38172,7 +38181,49 @@ function usePageManifest() {
|
|
|
38172
38181
|
}
|
|
38173
38182
|
function useSettoMenu(list2 = "menu") {
|
|
38174
38183
|
const manifest = usePageManifest();
|
|
38175
|
-
|
|
38184
|
+
const { canEdit, config } = useSetto();
|
|
38185
|
+
const blogEmpty = (config.blog?.posts.length ?? 0) === 0;
|
|
38186
|
+
const items = manifest ? canEdit ? ownerMenu(manifest, list2, blogEmpty) : visibleMenu(manifest, list2) : null;
|
|
38187
|
+
const dimmed = items?.filter((item) => item.dimmed).map((item) => item.href) ?? [];
|
|
38188
|
+
useDimmedLinks(dimmed, config.languages ?? []);
|
|
38189
|
+
return items;
|
|
38190
|
+
}
|
|
38191
|
+
const DIM_STYLE_ID = "setto-dimmed-links";
|
|
38192
|
+
const dimmedBy = /* @__PURE__ */ new Map();
|
|
38193
|
+
function drawDimmedLinks() {
|
|
38194
|
+
if (typeof document === "undefined") return;
|
|
38195
|
+
const selectors = [...new Set([...dimmedBy.values()].flat())];
|
|
38196
|
+
let style = document.getElementById(DIM_STYLE_ID);
|
|
38197
|
+
if (!selectors.length) {
|
|
38198
|
+
style?.remove();
|
|
38199
|
+
return;
|
|
38200
|
+
}
|
|
38201
|
+
if (!style) {
|
|
38202
|
+
style = document.createElement("style");
|
|
38203
|
+
style.id = DIM_STYLE_ID;
|
|
38204
|
+
document.head.appendChild(style);
|
|
38205
|
+
}
|
|
38206
|
+
style.textContent = `${selectors.join(",")}{opacity:.45;transition:opacity .15s}${selectors.map((s) => `${s}:hover`).join(",")}{opacity:.8}`;
|
|
38207
|
+
}
|
|
38208
|
+
function useDimmedLinks(hrefs, languages) {
|
|
38209
|
+
const key = hrefs.join("|");
|
|
38210
|
+
const langs = languages.join(",");
|
|
38211
|
+
useEffect(() => {
|
|
38212
|
+
if (!key) return;
|
|
38213
|
+
const mine = {};
|
|
38214
|
+
dimmedBy.set(
|
|
38215
|
+
mine,
|
|
38216
|
+
key.split("|").flatMap((href) => [
|
|
38217
|
+
`a[href="${href}"]`,
|
|
38218
|
+
...langs.split(",").slice(1).filter(Boolean).map((language) => `a[href="/${language}${href}"]`)
|
|
38219
|
+
])
|
|
38220
|
+
);
|
|
38221
|
+
drawDimmedLinks();
|
|
38222
|
+
return () => {
|
|
38223
|
+
dimmedBy.delete(mine);
|
|
38224
|
+
drawDimmedLinks();
|
|
38225
|
+
};
|
|
38226
|
+
}, [key, langs]);
|
|
38176
38227
|
}
|
|
38177
38228
|
function SettoPage({ pageId, path: path2, sections = {}, builtins, fallback = null }) {
|
|
38178
38229
|
const manifest = usePageManifest();
|
|
@@ -38427,13 +38478,21 @@ function blogStrings(language) {
|
|
|
38427
38478
|
function BlogBody({ nodes, language }) {
|
|
38428
38479
|
return /* @__PURE__ */ jsx(Fragment, { children: nodes.map((node2, i) => renderFlow(node2, i, language)) });
|
|
38429
38480
|
}
|
|
38481
|
+
function at(node2) {
|
|
38482
|
+
const range = node2.at;
|
|
38483
|
+
return Array.isArray(range) && range.length === 2 && range.every((n) => Number.isInteger(n)) ? { "data-setto-at": `${range[0]}:${range[1]}` } : {};
|
|
38484
|
+
}
|
|
38485
|
+
function atImage(node2, alt) {
|
|
38486
|
+
const where = at(node2);
|
|
38487
|
+
return where["data-setto-at"] ? { ...where, "data-setto-kind": "image", "data-setto-alt": alt } : {};
|
|
38488
|
+
}
|
|
38430
38489
|
function renderFlow(node2, key, language) {
|
|
38431
38490
|
switch (node2.type) {
|
|
38432
38491
|
case "paragraph":
|
|
38433
|
-
return /* @__PURE__ */ jsx("p", { children: renderPhrasing(node2.children) }, key);
|
|
38492
|
+
return /* @__PURE__ */ jsx("p", { ...at(node2), children: renderPhrasing(node2.children) }, key);
|
|
38434
38493
|
case "heading": {
|
|
38435
38494
|
const Tag = node2.depth === 2 ? "h2" : node2.depth === 3 ? "h3" : "h4";
|
|
38436
|
-
return /* @__PURE__ */ jsx(Tag, { children: renderPhrasing(node2.children) }, key);
|
|
38495
|
+
return /* @__PURE__ */ jsx(Tag, { ...at(node2), children: renderPhrasing(node2.children) }, key);
|
|
38437
38496
|
}
|
|
38438
38497
|
case "list": {
|
|
38439
38498
|
const items = node2.children.map((item, i) => /* @__PURE__ */ jsx("li", { children: item.children.map((child, j) => renderListChild(child, j, item.spread === true, language)) }, i));
|
|
@@ -38454,7 +38513,8 @@ function renderFlow(node2, key, language) {
|
|
|
38454
38513
|
}
|
|
38455
38514
|
}
|
|
38456
38515
|
function renderListChild(child, key, spread, language) {
|
|
38457
|
-
if (child.type === "paragraph" && !spread)
|
|
38516
|
+
if (child.type === "paragraph" && !spread)
|
|
38517
|
+
return /* @__PURE__ */ jsx("span", { ...at(child), children: renderPhrasing(child.children) }, key);
|
|
38458
38518
|
return renderFlow(child, key, language);
|
|
38459
38519
|
}
|
|
38460
38520
|
function renderPhrasing(children) {
|
|
@@ -38503,7 +38563,7 @@ function BlogComponent({ element: element2, language }) {
|
|
|
38503
38563
|
const props = attrs(element2);
|
|
38504
38564
|
switch (element2.name) {
|
|
38505
38565
|
case "Image":
|
|
38506
|
-
return props.src && props.alt !== void 0 ? /* @__PURE__ */ jsxs("figure", { className: "setto-blog__figure", children: [
|
|
38566
|
+
return props.src && props.alt !== void 0 ? /* @__PURE__ */ jsxs("figure", { className: "setto-blog__figure", ...atImage(element2, props.alt), children: [
|
|
38507
38567
|
/* @__PURE__ */ jsx(BlogImg, { src: props.src, alt: props.alt, sizes: "(min-width: 760px) 720px, 100vw" }),
|
|
38508
38568
|
props.caption ? /* @__PURE__ */ jsx("figcaption", { children: props.caption }) : null
|
|
38509
38569
|
] }) : null;
|
|
@@ -38514,7 +38574,7 @@ function BlogComponent({ element: element2, language }) {
|
|
|
38514
38574
|
return /* @__PURE__ */ jsxs("figure", { className: "setto-blog__gallery", children: [
|
|
38515
38575
|
/* @__PURE__ */ jsx("div", { className: "setto-blog__gallery-grid", children: images.map((image2, i) => {
|
|
38516
38576
|
const a = attrs(image2);
|
|
38517
|
-
return a.src ? /* @__PURE__ */ jsxs("figure", { className: "setto-blog__gallery-item", children: [
|
|
38577
|
+
return a.src ? /* @__PURE__ */ jsxs("figure", { className: "setto-blog__gallery-item", ...atImage(image2, a.alt ?? ""), children: [
|
|
38518
38578
|
/* @__PURE__ */ jsx(BlogImg, { src: a.src, alt: a.alt ?? "", sizes: "(min-width: 760px) 360px, 50vw" }),
|
|
38519
38579
|
a.caption ? /* @__PURE__ */ jsx("figcaption", { children: a.caption }) : null
|
|
38520
38580
|
] }, i) : null;
|
|
@@ -38629,16 +38689,19 @@ function useClearFixedHeader(ref, enabled) {
|
|
|
38629
38689
|
return clear;
|
|
38630
38690
|
}
|
|
38631
38691
|
function fixedAncestor(node2) {
|
|
38632
|
-
for (let
|
|
38633
|
-
if (getComputedStyle(
|
|
38692
|
+
for (let at2 = node2; at2 && at2 !== document.body; at2 = at2.parentElement) {
|
|
38693
|
+
if (getComputedStyle(at2).position === "fixed") return at2;
|
|
38634
38694
|
}
|
|
38635
38695
|
return null;
|
|
38636
38696
|
}
|
|
38637
38697
|
function BlogIndexView({ title, first, blogPath, ctx }) {
|
|
38638
38698
|
const posts = ctx.config.blog ? postsForLanguage(ctx.config.blog.posts, ctx.language, ctx.fallbackLanguage) : [];
|
|
38639
38699
|
const Heading = first ? "h1" : "h2";
|
|
38700
|
+
const { canEdit } = useSetto();
|
|
38701
|
+
const Owner = useSettoChromeSlot("blog-owner");
|
|
38640
38702
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38641
38703
|
/* @__PURE__ */ jsx(Heading, { className: "setto-blog__title", children: title }),
|
|
38704
|
+
canEdit && Owner ? /* @__PURE__ */ jsx("div", { className: "setto-blog__owner", "data-setto-ui": "", children: /* @__PURE__ */ jsx(Owner, { blogPath, language: ctx.language, posts: posts.length, Draft: BlogDraft }) }) : null,
|
|
38642
38705
|
posts.length === 0 ? /* @__PURE__ */ jsx("p", { className: "setto-blog__empty", children: ctx.strings.empty }) : /* @__PURE__ */ jsx("div", { className: "setto-blog__list", children: posts.map((post2) => /* @__PURE__ */ jsx(PostCard, { post: post2, blogPath, ctx, headingLevel: first ? "h2" : "h3" }, post2.slug)) })
|
|
38643
38706
|
] });
|
|
38644
38707
|
}
|
|
@@ -38698,18 +38761,35 @@ function BlogPostView({ slug, blogPath, ctx }) {
|
|
|
38698
38761
|
] });
|
|
38699
38762
|
}
|
|
38700
38763
|
const fm = post2?.frontmatter ?? summary;
|
|
38764
|
+
return /* @__PURE__ */ jsx(PostArticle, { frontmatter: fm, ctx, before: back, after: /* @__PURE__ */ jsx(ShareBar, { title: fm.title, strings: ctx.strings }), children: state === "ready" && post2 ? /* @__PURE__ */ jsx(BlogBody, { nodes: post2.body.children, language: ctx.language }) : /* @__PURE__ */ jsx("p", { className: "setto-blog__loading", "aria-live": "polite", children: ctx.strings.loading }) });
|
|
38765
|
+
}
|
|
38766
|
+
function PostArticle({
|
|
38767
|
+
frontmatter: fm,
|
|
38768
|
+
ctx,
|
|
38769
|
+
before,
|
|
38770
|
+
after,
|
|
38771
|
+
draft = false,
|
|
38772
|
+
children
|
|
38773
|
+
}) {
|
|
38774
|
+
const field = (name2) => draft ? { "data-setto-field": name2 } : {};
|
|
38775
|
+
const Title = draft ? "h2" : "h1";
|
|
38701
38776
|
return /* @__PURE__ */ jsxs("article", { className: "setto-blog__post", lang: fm.locale, children: [
|
|
38702
|
-
|
|
38777
|
+
before,
|
|
38703
38778
|
/* @__PURE__ */ jsxs("header", { className: "setto-blog__post-header", children: [
|
|
38704
38779
|
/* @__PURE__ */ jsx("time", { className: "setto-blog__date", dateTime: fm.date, children: formatPostDate(fm.date, ctx.language) }),
|
|
38705
|
-
/* @__PURE__ */ jsx(
|
|
38706
|
-
/* @__PURE__ */ jsx("p", { className: "setto-blog__lead", children: fm.description })
|
|
38780
|
+
/* @__PURE__ */ jsx(Title, { className: "setto-blog__post-title", ...field("title"), children: fm.title }),
|
|
38781
|
+
/* @__PURE__ */ jsx("p", { className: "setto-blog__lead", ...field("description"), children: fm.description })
|
|
38707
38782
|
] }),
|
|
38708
|
-
fm.cover ? /* @__PURE__ */ jsx("figure", { className: "setto-blog__cover", children: /* @__PURE__ */ jsx(BlogImg, { src: fm.cover, alt: "", sizes: "(min-width: 1040px) 960px, 100vw" }) }) : null,
|
|
38709
|
-
|
|
38710
|
-
|
|
38783
|
+
fm.cover ? /* @__PURE__ */ jsx("figure", { className: "setto-blog__cover", ...field("cover"), children: /* @__PURE__ */ jsx(BlogImg, { src: fm.cover, alt: "", sizes: "(min-width: 1040px) 960px, 100vw" }) }) : null,
|
|
38784
|
+
/* @__PURE__ */ jsx("div", { className: "setto-blog__prose", children }),
|
|
38785
|
+
after
|
|
38711
38786
|
] });
|
|
38712
38787
|
}
|
|
38788
|
+
function BlogDraft({ draft }) {
|
|
38789
|
+
useBlogStyles();
|
|
38790
|
+
const ctx = useBlogContext();
|
|
38791
|
+
return /* @__PURE__ */ jsx(PostArticle, { frontmatter: draft.frontmatter, ctx, draft: true, children: /* @__PURE__ */ jsx(BlogBody, { nodes: draft.body.children, language: ctx.language }) });
|
|
38792
|
+
}
|
|
38713
38793
|
function usePostTitle(title, siteName) {
|
|
38714
38794
|
useEffect(() => {
|
|
38715
38795
|
if (!title || typeof document === "undefined") return;
|
|
@@ -40815,6 +40895,7 @@ export {
|
|
|
40815
40895
|
BLOCK_TYPES,
|
|
40816
40896
|
BLOG_CSS,
|
|
40817
40897
|
BUILTIN_SECTION_TYPES,
|
|
40898
|
+
BlogDraft,
|
|
40818
40899
|
CHECKOUT_INTENT,
|
|
40819
40900
|
DEFAULT_LANGUAGE,
|
|
40820
40901
|
EMPTY_I18N_STORE_SNAPSHOT,
|
|
@@ -40888,6 +40969,7 @@ export {
|
|
|
40888
40969
|
normalisePath,
|
|
40889
40970
|
optimizedSrcSet,
|
|
40890
40971
|
optimizedUrl,
|
|
40972
|
+
ownerMenu,
|
|
40891
40973
|
pageById,
|
|
40892
40974
|
pageForPath,
|
|
40893
40975
|
pageTitleKey,
|