@seamlet/astro 0.5.1 → 0.6.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 +17 -0
- package/dist/chunk-3BS5CE26.js +20 -0
- package/dist/index.js +8 -0
- package/dist/protocol.d.ts +8 -1
- package/dist/protocol.js +8 -0
- package/dist/routes/own-photos.d.ts +5 -0
- package/dist/routes/own-photos.js +19 -0
- package/dist/site.d.ts +8 -0
- package/dist/site.js +2 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -125,6 +125,22 @@ A photo may carry the point that must stay in view when the site crops it, chose
|
|
|
125
125
|
/>
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
A photo may also be one of the site's own files, named by an address of the site (`/menu/01.jpg`) that the site turns into its image when it renders. Give `defineSeamletSite` a `photos` function that finds that image, and the CMS's editor shows the photo in its field too:
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
const MENU_FILES = import.meta.glob<{ default: ImageMetadata }>(
|
|
132
|
+
"./assets/menu/*.jpg",
|
|
133
|
+
{ eager: true },
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
export default defineSeamletSite({
|
|
137
|
+
id: "zerno",
|
|
138
|
+
schema,
|
|
139
|
+
pages: { "/": HomePage },
|
|
140
|
+
photos: (src) => MENU_FILES[src.replace("/menu/", "./assets/menu/")]?.default,
|
|
141
|
+
});
|
|
142
|
+
```
|
|
143
|
+
|
|
128
144
|
## Presets
|
|
129
145
|
|
|
130
146
|
Sets of fields almost every site has, edited the same way everywhere; they are plain groups and collections, rendered as the site likes:
|
|
@@ -178,6 +194,7 @@ What was opened stays open while the page is rendered anew after every edit.
|
|
|
178
194
|
|
|
179
195
|
- `/preview` and `/preview/<page>`: the preview the CMS's editor frames. `GET` shows the published content; `POST` with the content as JSON shows that content without saving it, which is how the editor shows every edit at once. Only the CMS may frame it (`Content-Security-Policy: frame-ancestors`), and it is never indexed or cached.
|
|
180
196
|
- The bridge on the preview: it tells the editor where the marked elements are and what a person does on the page, and types texts in place.
|
|
197
|
+
- `/seamlet-photos/<address>`: the site's own photo at an address its content gives it, found by `photos` of `defineSeamletSite`, for the CMS's editor.
|
|
181
198
|
- `/media/<site>/<file>`: the photos uploaded in the CMS, taken from it on request; a static build copies every uploaded photo its built pages refer to next to them, so a static host serves them too.
|
|
182
199
|
|
|
183
200
|
A site never renders content as raw HTML (`set:html`): the editor acts on what its preview says.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// src/own-photos.ts
|
|
2
|
+
var OWN_PHOTOS_PATH = "/seamlet-photos";
|
|
3
|
+
var UPLOADS_PATH = "/media/";
|
|
4
|
+
var PARENT_SEGMENT = "..";
|
|
5
|
+
function isOwnPhotoSrc(src) {
|
|
6
|
+
const isOnSite = src.startsWith("/") && !src.startsWith("//");
|
|
7
|
+
const isUpload = src.startsWith(UPLOADS_PATH);
|
|
8
|
+
const isPlainPath = !/[?#\\]/u.test(src);
|
|
9
|
+
const climbsUp = src.split("/").includes(PARENT_SEGMENT);
|
|
10
|
+
return isOnSite && !isUpload && isPlainPath && !climbsUp;
|
|
11
|
+
}
|
|
12
|
+
function ownPhotoPath(src) {
|
|
13
|
+
return isOwnPhotoSrc(src) ? `${OWN_PHOTOS_PATH}${src}` : void 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export {
|
|
17
|
+
OWN_PHOTOS_PATH,
|
|
18
|
+
isOwnPhotoSrc,
|
|
19
|
+
ownPhotoPath
|
|
20
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OWN_PHOTOS_PATH
|
|
3
|
+
} from "./chunk-3BS5CE26.js";
|
|
1
4
|
import {
|
|
2
5
|
isUploadedPhoto
|
|
3
6
|
} from "./chunk-P2OQOZBC.js";
|
|
@@ -89,6 +92,11 @@ function seamlet(options) {
|
|
|
89
92
|
entrypoint: "@seamlet/astro/routes/media",
|
|
90
93
|
prerender: false
|
|
91
94
|
});
|
|
95
|
+
injectRoute({
|
|
96
|
+
pattern: `${OWN_PHOTOS_PATH}/[...path]`,
|
|
97
|
+
entrypoint: "@seamlet/astro/routes/own-photos",
|
|
98
|
+
prerender: false
|
|
99
|
+
});
|
|
92
100
|
},
|
|
93
101
|
// A static host has no route to take the uploaded photos from the CMS on request: the photos
|
|
94
102
|
// the built pages refer to are copied next to them. Pages rendered on request take them
|
package/dist/protocol.d.ts
CHANGED
|
@@ -16,4 +16,11 @@ declare function imageFieldAt(schema: Fields, path: string | undefined): {
|
|
|
16
16
|
*/
|
|
17
17
|
declare function closestMarkedPath(path: FieldPath, isMarked: (path: string) => boolean): string | undefined;
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
/** Where a site hands out its own photos: `/seamlet-photos/menu/cafe/01.jpg`. */
|
|
20
|
+
declare const OWN_PHOTOS_PATH = "/seamlet-photos";
|
|
21
|
+
/** An address of the site itself that is not an upload, and that cannot climb out of the site. */
|
|
22
|
+
declare function isOwnPhotoSrc(src: string): boolean;
|
|
23
|
+
/** Where the site hands out its own photo; undefined for an upload or another site's address. */
|
|
24
|
+
declare function ownPhotoPath(src: string): string | undefined;
|
|
25
|
+
|
|
26
|
+
export { OWN_PHOTOS_PATH, carriesFiles, closestMarkedPath, imageFieldAt, isOwnPhotoSrc, ownPhotoPath };
|
package/dist/protocol.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
OWN_PHOTOS_PATH,
|
|
3
|
+
isOwnPhotoSrc,
|
|
4
|
+
ownPhotoPath
|
|
5
|
+
} from "./chunk-3BS5CE26.js";
|
|
1
6
|
import {
|
|
2
7
|
PROTOCOL_VERSION,
|
|
3
8
|
carriesFiles,
|
|
@@ -9,10 +14,13 @@ import {
|
|
|
9
14
|
} from "./chunk-XCBYYKWR.js";
|
|
10
15
|
import "./chunk-GLXC5OLC.js";
|
|
11
16
|
export {
|
|
17
|
+
OWN_PHOTOS_PATH,
|
|
12
18
|
PROTOCOL_VERSION,
|
|
13
19
|
carriesFiles,
|
|
14
20
|
closestMarkedPath,
|
|
15
21
|
imageFieldAt,
|
|
22
|
+
isOwnPhotoSrc,
|
|
23
|
+
ownPhotoPath,
|
|
16
24
|
readEditorMessage,
|
|
17
25
|
readPageMessage,
|
|
18
26
|
shortcutOf
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isOwnPhotoSrc
|
|
3
|
+
} from "../chunk-3BS5CE26.js";
|
|
4
|
+
|
|
5
|
+
// src/routes/own-photos.ts
|
|
6
|
+
import site from "virtual:seamlet/site";
|
|
7
|
+
var NOT_FOUND = 404;
|
|
8
|
+
var FOUND = 302;
|
|
9
|
+
var GET = ({ params, redirect }) => {
|
|
10
|
+
const src = `/${params["path"] ?? ""}`;
|
|
11
|
+
const photo = isOwnPhotoSrc(src) ? site.ownPhotoAt(src) : void 0;
|
|
12
|
+
if (photo === void 0) {
|
|
13
|
+
return new Response(null, { status: NOT_FOUND });
|
|
14
|
+
}
|
|
15
|
+
return redirect(photo.src, FOUND);
|
|
16
|
+
};
|
|
17
|
+
export {
|
|
18
|
+
GET
|
|
19
|
+
};
|
package/dist/site.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ImageMetadata } from 'astro';
|
|
1
2
|
import { AstroComponentFactory } from 'astro/runtime/server/index.js';
|
|
2
3
|
import { F as Fields, C as ContentOf } from './content-C_WpiWBm.js';
|
|
3
4
|
|
|
@@ -10,6 +11,11 @@ interface SeamletSiteDefinition<F extends Fields> {
|
|
|
10
11
|
* as their `content` prop. The CMS lists the same addresses for its editor.
|
|
11
12
|
*/
|
|
12
13
|
readonly pages: Readonly<Record<string, AstroComponentFactory>>;
|
|
14
|
+
/**
|
|
15
|
+
* The site's own photo at the address its content gives it (`/menu/cafe/01.jpg`), so the CMS's
|
|
16
|
+
* editor can show it in the photo's field. A site without own photos leaves it out.
|
|
17
|
+
*/
|
|
18
|
+
readonly photos?: (src: string) => ImageMetadata | undefined;
|
|
13
19
|
}
|
|
14
20
|
interface SeamletSite<F extends Fields = Fields> {
|
|
15
21
|
readonly id: string;
|
|
@@ -18,6 +24,8 @@ interface SeamletSite<F extends Fields = Fields> {
|
|
|
18
24
|
readonly pageAt: (rest: string | undefined) => AstroComponentFactory | undefined;
|
|
19
25
|
/** What the CMS published: the site's initial content until the first publication. */
|
|
20
26
|
readonly loadPublishedContent: () => Promise<ContentOf<F>>;
|
|
27
|
+
/** The site's own photo at an address its content gives it, if it has one there. */
|
|
28
|
+
readonly ownPhotoAt: (src: string) => ImageMetadata | undefined;
|
|
21
29
|
}
|
|
22
30
|
/** Describes the site for the integration: `src/seamlet.ts` exports it as its default. */
|
|
23
31
|
declare function defineSeamletSite<F extends Fields>(definition: SeamletSiteDefinition<F>): SeamletSite<F>;
|
package/dist/site.js
CHANGED
|
@@ -14,7 +14,8 @@ function defineSeamletSite(definition) {
|
|
|
14
14
|
loadPublishedContent: async () => {
|
|
15
15
|
const published = await fetchPublished(definition.id);
|
|
16
16
|
return parseContent(definition.schema, published).content;
|
|
17
|
-
}
|
|
17
|
+
},
|
|
18
|
+
ownPhotoAt: (src) => definition.photos?.(src)
|
|
18
19
|
};
|
|
19
20
|
}
|
|
20
21
|
async function fetchPublished(siteId) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seamlet/astro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "Connects an Astro site to the Seamlet CMS: the schema of its content, the preview the editor frames, and its published content.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -42,6 +42,10 @@
|
|
|
42
42
|
"./routes/media": {
|
|
43
43
|
"types": "./dist/routes/media.d.ts",
|
|
44
44
|
"default": "./dist/routes/media.js"
|
|
45
|
+
},
|
|
46
|
+
"./routes/own-photos": {
|
|
47
|
+
"types": "./dist/routes/own-photos.d.ts",
|
|
48
|
+
"default": "./dist/routes/own-photos.js"
|
|
45
49
|
}
|
|
46
50
|
},
|
|
47
51
|
"files": [
|