@seamlet/astro 0.11.2 → 0.12.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 +18 -6
- package/components/RichLine.astro +2 -5
- package/components/RichText.astro +2 -4
- package/dist/bridge.d.ts +2 -3
- package/dist/bridge.js +598 -374
- package/dist/{chunk-DRDPKFHZ.js → chunk-7GYJS7ZT.js} +386 -203
- package/dist/{chunk-2E7VDSUK.js → chunk-MW3BE5O6.js} +34 -43
- package/dist/chunk-QCVWHHJC.js +14 -0
- package/dist/{chunk-P2OQOZBC.js → chunk-QL4K4HR6.js} +8 -0
- package/dist/{chunk-3BS5CE26.js → chunk-W2LIOR2C.js} +6 -2
- package/dist/cli.js +96 -37
- package/dist/client.js +4 -1
- package/dist/index.js +52 -19
- package/dist/{messages-Dx0jNy3N.d.ts → messages-CvZhLRSE.d.ts} +29 -52
- package/dist/{content-6k-E7NWf.d.ts → parse-content-Eg8yRq_t.d.ts} +69 -1
- package/dist/preview-requests.d.ts +6 -1
- package/dist/preview-requests.js +3 -1
- package/dist/protocol.d.ts +31 -5
- package/dist/protocol.js +4 -3
- package/dist/routes/media.js +26 -5
- package/dist/routes/own-photos.js +2 -1
- package/dist/schema.d.ts +13 -8
- package/dist/schema.js +13 -1
- package/dist/site-description-Cg5KNhhG.d.ts +112 -0
- package/dist/site.d.ts +2 -2
- package/dist/site.js +83 -9
- package/package.json +1 -1
- package/routes/preview.astro +8 -11
- package/dist/parse-content-C9ldnmvj.d.ts +0 -69
- package/dist/site-description-4Jx6Nq6X.d.ts +0 -36
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ npx @seamlet/astro init --title "Кофейня «Зерно»" # seamlet.json
|
|
|
11
11
|
npx astro add @seamlet/astro node # the integration, and an adapter for the preview
|
|
12
12
|
```
|
|
13
13
|
|
|
14
|
-
`init` takes the id from the name in `package.json` unless `--id` gives it, and the CMS `https://cms.seamlet.ru` unless `--cms` names another; it never overwrites a file the site has, and says what to render in a page. The steps below are what it starts, one by one.
|
|
14
|
+
`init` takes the id from the name in `package.json` unless `--id` gives it, and the CMS `https://cms.seamlet.ru` unless `--cms` names another; it never overwrites a file the site has: a `seamlet.json` the site has already names the site for the modules it writes, and the three modules are written together or, when the site has any of them, not at all. It says what to render in a page. The steps below are what it starts, one by one.
|
|
15
15
|
|
|
16
16
|
1. Install the package. The site needs an adapter, because the preview is rendered on request; its own pages may stay static.
|
|
17
17
|
|
|
@@ -85,7 +85,7 @@ npx astro add @seamlet/astro node # the integration, and an ad
|
|
|
85
85
|
});
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
-
The CMS takes all of it from the site itself, so connecting a site, or changing its schema, needs no change of the CMS.
|
|
88
|
+
The CMS takes all of it from the site itself, so connecting a site, or changing its schema, needs no change of the CMS. `defineSeamletSite` checks the description exactly as the CMS reads it (`checkSiteDescription`), so a site the CMS would refuse stops its own build and says what to fix: a page address that is not `/` or lower-case segments without a trailing slash (`/menu`, not `/Menu` or `/menu/`), a first page other than `/`, initial content the CMS could not save, `searchTexts` that name no group of a `title` and a `description`, or a schema that cannot work. A schema cannot work with a field name that is empty, holds a dot or is a number (a path of a field reads them as its separator and as a record), an option of the wrong kind (`maxLength: "10"`), a `reference` to a collection it does not have, or an `itemTitle` that names no `text` or `link` field of the record.
|
|
89
89
|
|
|
90
90
|
5. Add the integration; it reads `seamlet.json` and `src/seamlet.ts` itself:
|
|
91
91
|
|
|
@@ -140,6 +140,18 @@ item: { name: text({ label: "Название" }), isHidden: toggle({ label: "С
|
|
|
140
140
|
// content.practices.filter((practice) => !practice.isHidden)
|
|
141
141
|
```
|
|
142
142
|
|
|
143
|
+
The preview renders the editor's draft before it is saved, and a draft may hold an address a link may not have (`javascript:…`, or one half typed). Put the address of a `link` or a `url` into `href` through `safeHref`, which gives it back when a link may lead there and nothing otherwise:
|
|
144
|
+
|
|
145
|
+
```astro
|
|
146
|
+
---
|
|
147
|
+
import { safeHref } from "@seamlet/astro/schema";
|
|
148
|
+
const href =
|
|
149
|
+
content.signup === null ? undefined : safeHref(content.signup.href);
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
{href !== undefined && <a href={href}>{content.signup?.text}</a>}
|
|
153
|
+
```
|
|
154
|
+
|
|
143
155
|
A photo may carry the point that must stay in view when the site crops it, chosen in the editor: put `imagePosition(photo)` into its `object-position` (the middle when no point is chosen):
|
|
144
156
|
|
|
145
157
|
```astro
|
|
@@ -188,7 +200,7 @@ import RichText from "@seamlet/astro/components/RichText.astro";
|
|
|
188
200
|
|
|
189
201
|
When the marked element holds the component alone, the editor types the text right on the page: a person clicks a paragraph and types, marks the selected words bold or italic (⌘B, ⌘I or the toolbar beside the selection) and puts a link on them. The element is then rendered with the same elements the component puts out, so style them from around it, never by classes of your own on them.
|
|
190
202
|
|
|
191
|
-
`plainTextOf` gives its words without marks, for a page title or a description.
|
|
203
|
+
`plainTextOf` gives its words without marks, for a page title or a description; `linesOf` gives its lines (the paragraphs and the items of its lists) in their order.
|
|
192
204
|
|
|
193
205
|
## Presets
|
|
194
206
|
|
|
@@ -237,15 +249,15 @@ A field is edited where it is seen, so the editor opens what hides it when a per
|
|
|
237
249
|
}
|
|
238
250
|
```
|
|
239
251
|
|
|
240
|
-
What was opened stays open while the page is rendered anew after every edit.
|
|
252
|
+
What was opened stays open while the page is rendered anew after every edit: a part is known again by its `id`, or else by the field marked on it, in it or around it.
|
|
241
253
|
|
|
242
254
|
## What the integration adds
|
|
243
255
|
|
|
244
|
-
- `/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.
|
|
256
|
+
- `/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; its refusals (a page the site does not have, a draft that is not JSON or is over 1 MB) say the same.
|
|
245
257
|
- 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, formatted ones too.
|
|
246
258
|
- `/seamlet/site.json`: what the site tells the CMS about itself (`SITE_DESCRIPTION_PATH`): its id and name from `seamlet.json`, its schema, the content it starts with and its pages. The CMS reads it with `readSiteDescription` whenever the site is opened in its editor.
|
|
247
259
|
- `/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.
|
|
248
|
-
- `/media/<site>/<file>`: the photos uploaded in the CMS, taken from it on request; a static build copies every uploaded
|
|
260
|
+
- `/media/<site>/<file>`: the photos uploaded for the site in the CMS, taken from it on request (`502` when the CMS does not answer in 10 seconds or fails); a static build copies every photo uploaded for the site that its built pages refer to next to them, a few at a time, so a static host serves them too. Loading the published content waits 30 seconds for the CMS and stops the build when it does not answer.
|
|
249
261
|
|
|
250
262
|
A site never renders content as raw HTML (`set:html`): the editor acts on what its preview says.
|
|
251
263
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
// The pieces of one line of formatted text with their marks.
|
|
3
|
-
import {
|
|
3
|
+
import { safeHref, type RichLine } from "@seamlet/astro/schema";
|
|
4
4
|
|
|
5
5
|
interface Props {
|
|
6
6
|
readonly spans: RichLine;
|
|
@@ -13,10 +13,7 @@ const pieces = spans.map((span) => ({
|
|
|
13
13
|
...span,
|
|
14
14
|
lines: span.text.split(LINE_BREAK),
|
|
15
15
|
// Content is checked when it is saved; a site never renders an address a link may not have.
|
|
16
|
-
safeHref:
|
|
17
|
-
span.href !== undefined && linkTargetOf(span.href) !== undefined
|
|
18
|
-
? span.href
|
|
19
|
-
: undefined,
|
|
16
|
+
safeHref: span.href === undefined ? undefined : safeHref(span.href),
|
|
20
17
|
}));
|
|
21
18
|
---
|
|
22
19
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// the words alone for an element that holds one line (`<p>`, `<h2>`). Nothing is rendered as raw
|
|
4
4
|
// HTML, and a link leads only where linkTargetOf allows. The site styles the elements from
|
|
5
5
|
// around it: `.about :global(a)`.
|
|
6
|
-
import type
|
|
6
|
+
import { linesOf, type RichText } from "@seamlet/astro/schema";
|
|
7
7
|
import RichLine from "./RichLine.astro";
|
|
8
8
|
|
|
9
9
|
interface Props {
|
|
@@ -13,9 +13,7 @@ interface Props {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
const { value, inline = false } = Astro.props;
|
|
16
|
-
const lines = value
|
|
17
|
-
block.kind === "paragraph" ? [block.spans] : block.items,
|
|
18
|
-
);
|
|
16
|
+
const lines = linesOf(value);
|
|
19
17
|
---
|
|
20
18
|
|
|
21
19
|
{inline
|
package/dist/bridge.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { F as Fields } from './content-
|
|
2
|
-
import { P as PageMessage, E as EditorMessage } from './messages-
|
|
3
|
-
import './parse-content-C9ldnmvj.js';
|
|
1
|
+
import { F as Fields } from './parse-content-Eg8yRq_t.js';
|
|
2
|
+
import { P as PageMessage, E as EditorMessage } from './messages-CvZhLRSE.js';
|
|
4
3
|
|
|
5
4
|
interface BridgeOptions {
|
|
6
5
|
/** The origin of the CMS whose editor may frame the page, such as `https://cms.example.com`. */
|