@sevenfold/setto-client 0.31.0 → 0.33.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/edit-mode/mount.d.ts +7 -2
- package/dist/index.d.ts +1 -0
- package/dist/lib/optimized-image.d.ts +40 -0
- package/dist/lib/page-store.d.ts +2 -0
- package/dist/provider.d.ts +19 -5
- package/dist/setto-client.js +119 -11
- package/dist/setto-client.js.map +1 -1
- package/dist/types.d.ts +9 -0
- package/package.json +1 -1
|
@@ -3,8 +3,13 @@ import type { ThemeStore } from '../lib/theme-store';
|
|
|
3
3
|
interface EditModeShellProps {
|
|
4
4
|
children: ReactNode;
|
|
5
5
|
themeStore: ThemeStore | null;
|
|
6
|
-
/**
|
|
6
|
+
/** Editing: the document layout, the section tools and the link hint. */
|
|
7
7
|
active: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The Setto menu, which an owner has whether or not they are editing: out of
|
|
10
|
+
* edit mode it is only the pencil. Defaults to `active`.
|
|
11
|
+
*/
|
|
12
|
+
menu?: boolean;
|
|
8
13
|
}
|
|
9
14
|
/**
|
|
10
15
|
* Edit mode: full-width page with a floating Setto FAB anchored bottom-left.
|
|
@@ -13,7 +18,7 @@ interface EditModeShellProps {
|
|
|
13
18
|
* Always mounted around the host app so toggling edit mode does not remount
|
|
14
19
|
* page content (which would replay GSAP / scroll-driven animations).
|
|
15
20
|
*/
|
|
16
|
-
export declare function EditModeShell({ children, themeStore, active }: EditModeShellProps): import("react/jsx-runtime").JSX.Element;
|
|
21
|
+
export declare function EditModeShell({ children, themeStore, active, menu }: EditModeShellProps): import("react/jsx-runtime").JSX.Element;
|
|
17
22
|
/** @deprecated Use EditModeShell */
|
|
18
23
|
export declare const EditModeMount: typeof EditModeShell;
|
|
19
24
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export { SettoIcon } from './SettoIcon';
|
|
|
12
12
|
export type { SettoIconProps, SettoIconRenderProps } from './SettoIcon';
|
|
13
13
|
export { SettoImage } from './SettoImage';
|
|
14
14
|
export type { SettoImageProps, ImageToolsProps } from './SettoImage';
|
|
15
|
+
export { SETTO_IMAGE_QUALITY, SETTO_IMAGE_WIDTHS, isOptimizable, optimizedSrcSet, optimizedUrl, settoVercelImagesConfig, } from './lib/optimized-image';
|
|
15
16
|
export { SettoRepeater } from './SettoRepeater';
|
|
16
17
|
export type { SettoRepeaterProps } from './SettoRepeater';
|
|
17
18
|
export { SettoForm, FORM_FIELD_TYPES, FORM_FIELD_TYPE_LABELS, fieldTypeHasOptions, fieldTypeHasPlaceholder, formFieldsPrefix, isFormFieldType, readLocaleFields, settoSubmissionUrl, } from './modules/forms';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Images through Vercel's Image Optimization, for sites that turned it on.
|
|
3
|
+
*
|
|
4
|
+
* A site keeps one original per image in its repository; the CDN makes each
|
|
5
|
+
* width on first request, in AVIF or WebP as the browser accepts, and caches
|
|
6
|
+
* it by the file's content. A site turns it on with two things that must
|
|
7
|
+
* agree: `"images": { "optimize": true }` in `setto.config.json`, and an
|
|
8
|
+
* `images` block in `vercel.json` whose `sizes` and `qualities` are exactly
|
|
9
|
+
* the constants below — Vercel refuses a `w` or `q` it was not given. The
|
|
10
|
+
* block, for copying: `settoVercelImagesConfig`.
|
|
11
|
+
*/
|
|
12
|
+
/** Phone, phone at 2–3×, tablet, laptop, wide and retina desktop. */
|
|
13
|
+
export declare const SETTO_IMAGE_WIDTHS: readonly [384, 640, 828, 1080, 1440, 1920, 2560];
|
|
14
|
+
/** One quality for every image, so each width is one cached variant rather than several. */
|
|
15
|
+
export declare const SETTO_IMAGE_QUALITY = 75;
|
|
16
|
+
/** The `images` block of `vercel.json` that matches `SettoImage`. */
|
|
17
|
+
export declare const settoVercelImagesConfig: {
|
|
18
|
+
readonly sizes: readonly [384, 640, 828, 1080, 1440, 1920, 2560];
|
|
19
|
+
readonly qualities: readonly [75];
|
|
20
|
+
readonly formats: readonly ["image/avif", "image/webp"];
|
|
21
|
+
readonly localPatterns: readonly [{
|
|
22
|
+
readonly pathname: "^/images/.*$";
|
|
23
|
+
readonly search: "";
|
|
24
|
+
}];
|
|
25
|
+
readonly minimumCacheTTL: 2678400;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* 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.
|
|
31
|
+
*/
|
|
32
|
+
export declare function isOptimizable(src: string | null | undefined): src is string;
|
|
33
|
+
/**
|
|
34
|
+
* Where there is no optimizer to ask: the Vite dev server and a local
|
|
35
|
+
* preview. A deployment elsewhere without one (a build sandbox) is caught by
|
|
36
|
+
* the image's own error instead.
|
|
37
|
+
*/
|
|
38
|
+
export declare function hasNoOptimizer(hostname: string): boolean;
|
|
39
|
+
export declare function optimizedUrl(src: string, width: number): string;
|
|
40
|
+
export declare function optimizedSrcSet(src: string): string;
|
package/dist/lib/page-store.d.ts
CHANGED
|
@@ -30,6 +30,8 @@ export declare class PageStore {
|
|
|
30
30
|
constructor(initial: PagesManifest | null);
|
|
31
31
|
snapshot(): PageStoreSnapshot;
|
|
32
32
|
subscribe(listener: Listener): () => void;
|
|
33
|
+
/** The manifest as published, to tell which sections the owner changed. */
|
|
34
|
+
get baselineManifest(): PagesManifest | null;
|
|
33
35
|
get manifest(): PagesManifest | null;
|
|
34
36
|
/** True once the site has a manifest to edit. */
|
|
35
37
|
has(): boolean;
|
package/dist/provider.d.ts
CHANGED
|
@@ -13,8 +13,20 @@ export interface SettoContextValue {
|
|
|
13
13
|
session: Session | null;
|
|
14
14
|
/** True while the initial auth state is being read from local storage. */
|
|
15
15
|
authLoading: boolean;
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* True while the owner is editing: `canEdit`, and they chose to edit. What
|
|
18
|
+
* makes text editable, shows hidden sections and draws the section tools.
|
|
19
|
+
*/
|
|
17
20
|
editMode: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* True when this person may edit this site: signed in, a member, the site is
|
|
23
|
+
* paid for, and this is not `/setto`. The Setto menu is drawn whenever this
|
|
24
|
+
* is; outside `editMode` it shows the site as a visitor sees it.
|
|
25
|
+
* Absent on a client older than 0.33, where `editMode` meant this.
|
|
26
|
+
*/
|
|
27
|
+
canEdit: boolean;
|
|
28
|
+
/** Switch editing on or off. Remembered for this site in this browser. */
|
|
29
|
+
setEditing: (on: boolean) => void;
|
|
18
30
|
/** Site row matching `config.siteId`, or `null` if the user has no access. */
|
|
19
31
|
currentSite: SiteRow | null;
|
|
20
32
|
/** All sites the user can access (loaded after sign-in). */
|
|
@@ -65,13 +77,15 @@ export interface SettoProviderProps {
|
|
|
65
77
|
* Wraps the host app. Initialises Supabase, the API client, and listens for
|
|
66
78
|
* auth changes. Mounts the edit toolbar and enables inline editing when active.
|
|
67
79
|
*
|
|
68
|
-
*
|
|
80
|
+
* The owner may edit (`canEdit`) when ALL of:
|
|
69
81
|
* 1. There is an authenticated Supabase session.
|
|
70
82
|
* 2. The user has access to `config.siteId` in the Setto sites table.
|
|
71
|
-
* 3. The
|
|
83
|
+
* 3. The site is paid for (`live`).
|
|
84
|
+
* 4. The current path is not the `/setto` admin SPA.
|
|
72
85
|
*
|
|
73
|
-
* Once an editor signs in via `/setto
|
|
74
|
-
*
|
|
86
|
+
* Once an editor signs in via `/setto` they stay signed in until they sign out
|
|
87
|
+
* there. Whether they are editing is their own switch (`setEditing`): the
|
|
88
|
+
* Setto menu's pencil turns it on, and publishing turns it off.
|
|
75
89
|
*/
|
|
76
90
|
export declare function SettoProvider({ config, children }: SettoProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
77
91
|
export declare function useSetto(): SettoContextValue;
|
package/dist/setto-client.js
CHANGED
|
@@ -21783,6 +21783,10 @@ class PageStore {
|
|
|
21783
21783
|
this.listeners.add(listener);
|
|
21784
21784
|
return () => this.listeners.delete(listener);
|
|
21785
21785
|
}
|
|
21786
|
+
/** The manifest as published, to tell which sections the owner changed. */
|
|
21787
|
+
get baselineManifest() {
|
|
21788
|
+
return this.baseline;
|
|
21789
|
+
}
|
|
21786
21790
|
get manifest() {
|
|
21787
21791
|
return this.data;
|
|
21788
21792
|
}
|
|
@@ -22261,7 +22265,7 @@ const pillStyle = {
|
|
|
22261
22265
|
whiteSpace: "nowrap",
|
|
22262
22266
|
boxShadow: "0 8px 24px rgba(33, 23, 17, 0.35), 0 2px 6px rgba(33, 23, 17, 0.2)"
|
|
22263
22267
|
};
|
|
22264
|
-
function EditModeShell({ children, themeStore, active }) {
|
|
22268
|
+
function EditModeShell({ children, themeStore, active, menu = active }) {
|
|
22265
22269
|
useSettoDocumentLayout(active);
|
|
22266
22270
|
const Toolbar = useSettoChromeSlot("toolbar");
|
|
22267
22271
|
const SectionTools = useSettoChromeSlot("section-toolbar");
|
|
@@ -22270,15 +22274,30 @@ function EditModeShell({ children, themeStore, active }) {
|
|
|
22270
22274
|
const [hintRoot, setHintRoot] = useState(null);
|
|
22271
22275
|
const [sectionToolbarRoot, setSectionToolbarRoot] = useState(null);
|
|
22272
22276
|
useEffect(() => {
|
|
22273
|
-
if (!
|
|
22277
|
+
if (!menu) {
|
|
22274
22278
|
setToolbarRoot(null);
|
|
22275
|
-
setHintRoot(null);
|
|
22276
|
-
setSectionToolbarRoot(null);
|
|
22277
22279
|
return;
|
|
22278
22280
|
}
|
|
22279
22281
|
const toolbar = document.createElement("div");
|
|
22280
22282
|
toolbar.id = "setto-toolbar-root";
|
|
22283
|
+
Object.assign(toolbar.style, {
|
|
22284
|
+
position: "fixed",
|
|
22285
|
+
right: "var(--setto-fab-inset, 16px)",
|
|
22286
|
+
bottom: "var(--setto-fab-inset, 16px)",
|
|
22287
|
+
zIndex: "2147483647"
|
|
22288
|
+
});
|
|
22281
22289
|
document.body.appendChild(toolbar);
|
|
22290
|
+
setToolbarRoot(toolbar);
|
|
22291
|
+
return () => {
|
|
22292
|
+
toolbar.remove();
|
|
22293
|
+
};
|
|
22294
|
+
}, [menu]);
|
|
22295
|
+
useEffect(() => {
|
|
22296
|
+
if (!active) {
|
|
22297
|
+
setHintRoot(null);
|
|
22298
|
+
setSectionToolbarRoot(null);
|
|
22299
|
+
return;
|
|
22300
|
+
}
|
|
22282
22301
|
const hint = document.createElement("div");
|
|
22283
22302
|
hint.id = "setto-hint-root";
|
|
22284
22303
|
hint.style.pointerEvents = "none";
|
|
@@ -22287,18 +22306,16 @@ function EditModeShell({ children, themeStore, active }) {
|
|
|
22287
22306
|
sectionBar.id = "setto-section-toolbar-root";
|
|
22288
22307
|
sectionBar.style.pointerEvents = "none";
|
|
22289
22308
|
document.body.appendChild(sectionBar);
|
|
22290
|
-
setToolbarRoot(toolbar);
|
|
22291
22309
|
setHintRoot(hint);
|
|
22292
22310
|
setSectionToolbarRoot(sectionBar);
|
|
22293
22311
|
return () => {
|
|
22294
|
-
toolbar.remove();
|
|
22295
22312
|
hint.remove();
|
|
22296
22313
|
sectionBar.remove();
|
|
22297
22314
|
};
|
|
22298
22315
|
}, [active]);
|
|
22299
22316
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
22300
22317
|
children,
|
|
22301
|
-
|
|
22318
|
+
menu && toolbarRoot ? createPortal(Toolbar ? /* @__PURE__ */ jsx(Toolbar, {}) : /* @__PURE__ */ jsx(ToolbarUnavailable, {}), toolbarRoot) : null,
|
|
22302
22319
|
active && hintRoot && LinkHint ? createPortal(/* @__PURE__ */ jsx(LinkHint, {}), hintRoot) : null,
|
|
22303
22320
|
active && sectionToolbarRoot && themeStore && SectionTools ? createPortal(/* @__PURE__ */ jsx(SectionTools, {}), sectionToolbarRoot) : null
|
|
22304
22321
|
] });
|
|
@@ -36606,7 +36623,16 @@ function SettoProvider({ config, children }) {
|
|
|
36606
36623
|
pageStoreRef.current = new PageStore(bundledManifest(config.pages));
|
|
36607
36624
|
setStoreReady(true);
|
|
36608
36625
|
}, [i18n, config.theme, config.pages]);
|
|
36609
|
-
const
|
|
36626
|
+
const canEdit = !!session && access.currentSite?.status === "live" && !onAdminRoute && !authLoading && !access.loading;
|
|
36627
|
+
const [editing, setEditingState] = useState(() => readEditing(config.siteId));
|
|
36628
|
+
const setEditing = useCallback(
|
|
36629
|
+
(on) => {
|
|
36630
|
+
writeEditing(config.siteId, on);
|
|
36631
|
+
setEditingState(on);
|
|
36632
|
+
},
|
|
36633
|
+
[config.siteId]
|
|
36634
|
+
);
|
|
36635
|
+
const editMode = canEdit && editing;
|
|
36610
36636
|
const [selectedSectionId, setSelectedSectionId] = useState(null);
|
|
36611
36637
|
const selectSection = useCallback((id) => setSelectedSectionId(id), []);
|
|
36612
36638
|
const [guestEdit, setGuestEdit] = useState(false);
|
|
@@ -36624,6 +36650,8 @@ function SettoProvider({ config, children }) {
|
|
|
36624
36650
|
session,
|
|
36625
36651
|
authLoading,
|
|
36626
36652
|
editMode,
|
|
36653
|
+
canEdit,
|
|
36654
|
+
setEditing,
|
|
36627
36655
|
currentSite: access.currentSite,
|
|
36628
36656
|
sites: access.sites,
|
|
36629
36657
|
store: storeReady ? storeRef.current : null,
|
|
@@ -36636,13 +36664,29 @@ function SettoProvider({ config, children }) {
|
|
|
36636
36664
|
setGuestEdit
|
|
36637
36665
|
};
|
|
36638
36666
|
const editShellActive = editMode && !!value.store;
|
|
36667
|
+
const menuShown = canEdit && !!value.store;
|
|
36639
36668
|
return /* @__PURE__ */ jsx(SettoContext.Provider, { value, children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
36640
|
-
/* @__PURE__ */ jsx(EditModeShell, { active: editShellActive, themeStore: value.themeStore, children }),
|
|
36669
|
+
/* @__PURE__ */ jsx(EditModeShell, { active: editShellActive, menu: menuShown, themeStore: value.themeStore, children }),
|
|
36641
36670
|
/* @__PURE__ */ jsx(SettoChrome, {}),
|
|
36642
36671
|
/* @__PURE__ */ jsx(SettoChat, {}),
|
|
36643
36672
|
/* @__PURE__ */ jsx(AutoLanguageSwitcher, { languages })
|
|
36644
36673
|
] }) });
|
|
36645
36674
|
}
|
|
36675
|
+
const editingKey = (siteId) => `setto-editing:${siteId}`;
|
|
36676
|
+
function readEditing(siteId) {
|
|
36677
|
+
try {
|
|
36678
|
+
return window.localStorage.getItem(editingKey(siteId)) === "1";
|
|
36679
|
+
} catch {
|
|
36680
|
+
return false;
|
|
36681
|
+
}
|
|
36682
|
+
}
|
|
36683
|
+
function writeEditing(siteId, on) {
|
|
36684
|
+
try {
|
|
36685
|
+
if (on) window.localStorage.setItem(editingKey(siteId), "1");
|
|
36686
|
+
else window.localStorage.removeItem(editingKey(siteId));
|
|
36687
|
+
} catch {
|
|
36688
|
+
}
|
|
36689
|
+
}
|
|
36646
36690
|
function useSetto() {
|
|
36647
36691
|
const ctx = useContext(SettoContext);
|
|
36648
36692
|
if (!ctx) {
|
|
@@ -37505,6 +37549,29 @@ function SettoIcon({ k, icons, size = 24, className, style }) {
|
|
|
37505
37549
|
)
|
|
37506
37550
|
] });
|
|
37507
37551
|
}
|
|
37552
|
+
const SETTO_IMAGE_WIDTHS = [384, 640, 828, 1080, 1440, 1920, 2560];
|
|
37553
|
+
const SETTO_IMAGE_QUALITY = 75;
|
|
37554
|
+
const settoVercelImagesConfig = {
|
|
37555
|
+
sizes: [...SETTO_IMAGE_WIDTHS],
|
|
37556
|
+
qualities: [SETTO_IMAGE_QUALITY],
|
|
37557
|
+
formats: ["image/avif", "image/webp"],
|
|
37558
|
+
localPatterns: [{ pathname: "^/images/.*$", search: "" }],
|
|
37559
|
+
minimumCacheTTL: 2678400
|
|
37560
|
+
};
|
|
37561
|
+
const OPTIMIZABLE = /\.(jpe?g|png|webp|avif)$/i;
|
|
37562
|
+
function isOptimizable(src) {
|
|
37563
|
+
if (!src || !src.startsWith("/images/")) return false;
|
|
37564
|
+
return OPTIMIZABLE.test(src.split(/[?#]/)[0]);
|
|
37565
|
+
}
|
|
37566
|
+
function hasNoOptimizer(hostname) {
|
|
37567
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname.endsWith(".localhost");
|
|
37568
|
+
}
|
|
37569
|
+
function optimizedUrl(src, width) {
|
|
37570
|
+
return `/_vercel/image?url=${encodeURIComponent(src)}&w=${width}&q=${SETTO_IMAGE_QUALITY}`;
|
|
37571
|
+
}
|
|
37572
|
+
function optimizedSrcSet(src) {
|
|
37573
|
+
return SETTO_IMAGE_WIDTHS.map((w) => `${optimizedUrl(src, w)} ${w}w`).join(", ");
|
|
37574
|
+
}
|
|
37508
37575
|
const ACCEPT = "image/png,image/jpeg,image/webp,image/svg+xml";
|
|
37509
37576
|
function setSrcAllLanguages(store, i18n, srcKey, value) {
|
|
37510
37577
|
const langs = i18n.languages?.length ? i18n.languages : [i18n.language];
|
|
@@ -37512,9 +37579,34 @@ function setSrcAllLanguages(store, i18n, srcKey, value) {
|
|
|
37512
37579
|
store.set(srcKey, lng, value);
|
|
37513
37580
|
}
|
|
37514
37581
|
}
|
|
37582
|
+
function PublishedImage({
|
|
37583
|
+
src,
|
|
37584
|
+
optimize,
|
|
37585
|
+
sizes,
|
|
37586
|
+
srcSet,
|
|
37587
|
+
onError,
|
|
37588
|
+
...rest
|
|
37589
|
+
}) {
|
|
37590
|
+
const [direct, setDirect] = useState(false);
|
|
37591
|
+
const optimized = optimize && !direct && !srcSet && isOptimizable(src) && !(typeof window !== "undefined" && hasNoOptimizer(window.location.hostname));
|
|
37592
|
+
if (!optimized) return /* @__PURE__ */ jsx("img", { src, srcSet, sizes, onError, ...rest });
|
|
37593
|
+
return /* @__PURE__ */ jsx(
|
|
37594
|
+
"img",
|
|
37595
|
+
{
|
|
37596
|
+
src: optimizedUrl(src, 1080),
|
|
37597
|
+
srcSet: optimizedSrcSet(src),
|
|
37598
|
+
sizes: sizes ?? "100vw",
|
|
37599
|
+
onError: (e) => {
|
|
37600
|
+
setDirect(true);
|
|
37601
|
+
onError?.(e);
|
|
37602
|
+
},
|
|
37603
|
+
...rest
|
|
37604
|
+
}
|
|
37605
|
+
);
|
|
37606
|
+
}
|
|
37515
37607
|
function SettoImage({ srcKey, alt, className, style, ...rest }) {
|
|
37516
37608
|
const { t, i18n } = useTranslation();
|
|
37517
|
-
const { editMode, store, assetStore } = useSetto();
|
|
37609
|
+
const { editMode, store, assetStore, config } = useSetto();
|
|
37518
37610
|
const fileRef = useRef(null);
|
|
37519
37611
|
const [hovered, setHovered] = useState(false);
|
|
37520
37612
|
const [uploading, setUploading] = useState(false);
|
|
@@ -37534,7 +37626,17 @@ function SettoImage({ srcKey, alt, className, style, ...rest }) {
|
|
|
37534
37626
|
const previewUrl = assetStore?.getPreviewUrl(srcKey);
|
|
37535
37627
|
const src = previewUrl ?? srcPath;
|
|
37536
37628
|
if (!editMode) {
|
|
37537
|
-
return /* @__PURE__ */ jsx(
|
|
37629
|
+
return /* @__PURE__ */ jsx(
|
|
37630
|
+
PublishedImage,
|
|
37631
|
+
{
|
|
37632
|
+
src: srcPath,
|
|
37633
|
+
optimize: config.images?.optimize === true,
|
|
37634
|
+
alt,
|
|
37635
|
+
className,
|
|
37636
|
+
style,
|
|
37637
|
+
...rest
|
|
37638
|
+
}
|
|
37639
|
+
);
|
|
37538
37640
|
}
|
|
37539
37641
|
const isFullWidth = className?.includes("w-full");
|
|
37540
37642
|
const isFullHeight = className?.includes("h-full");
|
|
@@ -40011,6 +40113,8 @@ export {
|
|
|
40011
40113
|
PAGES_PATH,
|
|
40012
40114
|
PageStore,
|
|
40013
40115
|
SETTO_BASE,
|
|
40116
|
+
SETTO_IMAGE_QUALITY,
|
|
40117
|
+
SETTO_IMAGE_WIDTHS,
|
|
40014
40118
|
SETTO_MODULES,
|
|
40015
40119
|
SettoAdminApp,
|
|
40016
40120
|
SettoAnimation,
|
|
@@ -40051,11 +40155,14 @@ export {
|
|
|
40051
40155
|
isAdminRoute,
|
|
40052
40156
|
isFormFieldType,
|
|
40053
40157
|
isLinkContext,
|
|
40158
|
+
isOptimizable,
|
|
40054
40159
|
isSafeHref,
|
|
40055
40160
|
languageFromPath,
|
|
40056
40161
|
languageName,
|
|
40057
40162
|
nodeChildren,
|
|
40058
40163
|
normalisePath,
|
|
40164
|
+
optimizedSrcSet,
|
|
40165
|
+
optimizedUrl,
|
|
40059
40166
|
pageById,
|
|
40060
40167
|
pageForPath,
|
|
40061
40168
|
pageTitleKey,
|
|
@@ -40067,6 +40174,7 @@ export {
|
|
|
40067
40174
|
redirectForVisitor,
|
|
40068
40175
|
serialiseManifest,
|
|
40069
40176
|
settoSubmissionUrl,
|
|
40177
|
+
settoVercelImagesConfig,
|
|
40070
40178
|
siteHomeUrl,
|
|
40071
40179
|
siteLanguages,
|
|
40072
40180
|
useCoarsePointer,
|