@seamlet/astro 0.4.0 → 0.5.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 CHANGED
@@ -178,7 +178,7 @@ What was opened stays open while the page is rendered anew after every edit.
178
178
 
179
179
  - `/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
180
  - 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.
181
- - `/media/<site>/<file>`: the photos uploaded in the CMS, taken from it.
181
+ - `/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
182
 
183
183
  A site never renders content as raw HTML (`set:html`): the editor acts on what its preview says.
184
184
 
package/dist/index.js CHANGED
@@ -1,5 +1,53 @@
1
+ import {
2
+ isUploadedPhoto
3
+ } from "./chunk-P2OQOZBC.js";
4
+
1
5
  // src/index.ts
2
6
  import { fileURLToPath } from "url";
7
+
8
+ // src/uploaded-photos.ts
9
+ import { mkdir, readdir, readFile, writeFile } from "fs/promises";
10
+ import { dirname, join } from "path";
11
+ var PHOTO_ADDRESS = /\/media\/([a-z0-9-]+)\/([A-Za-z0-9_-]+\.webp)/gu;
12
+ var HTML_EXTENSION = ".html";
13
+ function uploadedPhotoAddresses(html) {
14
+ const addresses = [...html.matchAll(PHOTO_ADDRESS)].flatMap(
15
+ ([address, , fileName]) => isUploadedPhoto(fileName) ? [address] : []
16
+ );
17
+ return [...new Set(addresses)];
18
+ }
19
+ async function copyUploadedPhotos(options) {
20
+ const pages = await htmlFilesIn(options.directory);
21
+ const texts = await Promise.all(pages.map((page) => readFile(page, "utf8")));
22
+ const addresses = new Set(texts.flatMap(uploadedPhotoAddresses));
23
+ await Promise.all(
24
+ [...addresses].map(
25
+ (address) => copyPhoto(address, options.directory, options.cmsOrigin)
26
+ )
27
+ );
28
+ return addresses.size;
29
+ }
30
+ async function copyPhoto(address, directory, cmsOrigin) {
31
+ const url = new URL(address, cmsOrigin);
32
+ const response = await fetch(url);
33
+ if (!response.ok) {
34
+ throw new Error(
35
+ `Copying the photo ${url.href} into the build failed with status ${String(response.status)}`
36
+ );
37
+ }
38
+ const target = join(directory, address);
39
+ await mkdir(dirname(target), { recursive: true });
40
+ await writeFile(target, new Uint8Array(await response.arrayBuffer()));
41
+ }
42
+ async function htmlFilesIn(directory) {
43
+ const entries = await readdir(directory, {
44
+ recursive: true,
45
+ withFileTypes: true
46
+ });
47
+ return entries.filter((entry) => entry.isFile() && entry.name.endsWith(HTML_EXTENSION)).map((entry) => join(entry.parentPath, entry.name));
48
+ }
49
+
50
+ // src/index.ts
3
51
  var CONFIG_MODULE = "virtual:seamlet/config";
4
52
  var SITE_MODULE = "virtual:seamlet/site";
5
53
  var RESOLVED_CONFIG_MODULE = `\0${CONFIG_MODULE}`;
@@ -41,6 +89,16 @@ function seamlet(options) {
41
89
  entrypoint: "@seamlet/astro/routes/media",
42
90
  prerender: false
43
91
  });
92
+ },
93
+ // A static host has no route to take the uploaded photos from the CMS on request: the photos
94
+ // the built pages refer to are copied next to them. Pages rendered on request take them
95
+ // through the route above.
96
+ "astro:build:done": async ({ dir, logger }) => {
97
+ const copied = await copyUploadedPhotos({
98
+ directory: fileURLToPath(dir),
99
+ cmsOrigin
100
+ });
101
+ if (copied > 0) logger.info(`copied ${String(copied)} uploaded photos`);
44
102
  }
45
103
  }
46
104
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seamlet/astro",
3
- "version": "0.4.0",
3
+ "version": "0.5.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",