@seamlet/astro 0.6.0 → 0.8.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 +42 -17
- package/components/RichLine.astro +37 -0
- package/components/RichText.astro +42 -0
- package/dist/bridge.d.ts +3 -3
- package/dist/bridge.js +263 -13
- package/dist/chunk-27XIZEVS.js +705 -0
- package/dist/{chunk-GLXC5OLC.js → chunk-ZUJEM3P7.js} +127 -0
- package/dist/{content-C_WpiWBm.d.ts → content-6k-E7NWf.d.ts} +48 -4
- package/dist/{messages-CBf5diaN.d.ts → messages-Dx0jNy3N.d.ts} +76 -4
- package/dist/{parse-content-9RIWhb6z.d.ts → parse-content-C9ldnmvj.d.ts} +1 -1
- package/dist/protocol.d.ts +16 -4
- package/dist/protocol.js +26 -4
- package/dist/schema.d.ts +4 -4
- package/dist/schema.js +13 -1
- package/dist/site.d.ts +1 -1
- package/dist/site.js +1 -1
- package/package.json +5 -3
- package/dist/chunk-XCBYYKWR.js +0 -160
|
@@ -5,6 +5,9 @@ function defineSchema(fields) {
|
|
|
5
5
|
function text(options) {
|
|
6
6
|
return { kind: "text", ...options };
|
|
7
7
|
}
|
|
8
|
+
function richText(options) {
|
|
9
|
+
return { kind: "richText", ...options };
|
|
10
|
+
}
|
|
8
11
|
function number(options) {
|
|
9
12
|
return { kind: "number", ...options };
|
|
10
13
|
}
|
|
@@ -54,6 +57,7 @@ function defaultValue(field) {
|
|
|
54
57
|
return false;
|
|
55
58
|
case "choices":
|
|
56
59
|
case "references":
|
|
60
|
+
case "richText":
|
|
57
61
|
return [];
|
|
58
62
|
case "number":
|
|
59
63
|
case "date":
|
|
@@ -147,6 +151,102 @@ function withoutPrefix(address, prefix) {
|
|
|
147
151
|
return hasPrefix ? address.slice(prefix.length) : void 0;
|
|
148
152
|
}
|
|
149
153
|
|
|
154
|
+
// src/schema/rich-text.ts
|
|
155
|
+
var PARAGRAPH_BREAK = /\n\s*\n/u;
|
|
156
|
+
var PARAGRAPH_SEPARATOR = "\n\n";
|
|
157
|
+
var LINE_SEPARATOR = "\n";
|
|
158
|
+
var SPACE = " ";
|
|
159
|
+
function richTextOf(plain) {
|
|
160
|
+
return plain.split(PARAGRAPH_BREAK).map((paragraph) => paragraph.trim()).filter((paragraph) => paragraph !== "").map((paragraph) => ({ kind: "paragraph", spans: [{ text: paragraph }] }));
|
|
161
|
+
}
|
|
162
|
+
function plainTextOf(text2) {
|
|
163
|
+
return text2.map(plainBlockOf).join(PARAGRAPH_SEPARATOR);
|
|
164
|
+
}
|
|
165
|
+
function linkAddressesOf(text2) {
|
|
166
|
+
return linesOf(text2).flatMap(
|
|
167
|
+
(line) => line.flatMap((span) => span.href === void 0 ? [] : [span.href])
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
function asOneParagraph(text2) {
|
|
171
|
+
const lines = linesOf(text2).filter((line) => line.length > 0);
|
|
172
|
+
if (lines.length === 0) return [];
|
|
173
|
+
const spans = lines.flatMap(
|
|
174
|
+
(line, index) => index === 0 ? line : [{ text: SPACE }, ...line]
|
|
175
|
+
);
|
|
176
|
+
return [{ kind: "paragraph", spans: normalizedLine(spans) }];
|
|
177
|
+
}
|
|
178
|
+
function readRichText(input) {
|
|
179
|
+
if (!Array.isArray(input)) return void 0;
|
|
180
|
+
const blocks = input.map(readBlock);
|
|
181
|
+
const isEveryBlockRead = blocks.every((block) => block !== void 0);
|
|
182
|
+
if (!isEveryBlockRead) return void 0;
|
|
183
|
+
return blocks.filter(hasWords);
|
|
184
|
+
}
|
|
185
|
+
function normalizedLine(spans) {
|
|
186
|
+
return spans.filter((span) => span.text !== "").reduce((joined, span) => {
|
|
187
|
+
const previous = joined.at(-1);
|
|
188
|
+
if (previous !== void 0 && haveSameMarks(previous, span)) {
|
|
189
|
+
return [
|
|
190
|
+
...joined.slice(0, -1),
|
|
191
|
+
{ ...previous, text: previous.text + span.text }
|
|
192
|
+
];
|
|
193
|
+
}
|
|
194
|
+
return [...joined, span];
|
|
195
|
+
}, []);
|
|
196
|
+
}
|
|
197
|
+
function readBlock(input) {
|
|
198
|
+
if (!isObject(input)) return void 0;
|
|
199
|
+
if (input["kind"] === "paragraph") {
|
|
200
|
+
const spans = readLine(input["spans"]);
|
|
201
|
+
return spans === void 0 ? void 0 : { kind: "paragraph", spans };
|
|
202
|
+
}
|
|
203
|
+
if (input["kind"] === "list" && Array.isArray(input["items"])) {
|
|
204
|
+
const items = input["items"].map(readLine);
|
|
205
|
+
const isEveryItemRead = items.every((item) => item !== void 0);
|
|
206
|
+
if (!isEveryItemRead) return void 0;
|
|
207
|
+
return { kind: "list", items: items.filter((item) => item.length > 0) };
|
|
208
|
+
}
|
|
209
|
+
return void 0;
|
|
210
|
+
}
|
|
211
|
+
function readLine(input) {
|
|
212
|
+
if (!Array.isArray(input)) return void 0;
|
|
213
|
+
const spans = input.map(readSpan);
|
|
214
|
+
const isEverySpanRead = spans.every((span) => span !== void 0);
|
|
215
|
+
return isEverySpanRead ? normalizedLine(spans) : void 0;
|
|
216
|
+
}
|
|
217
|
+
function readSpan(input) {
|
|
218
|
+
if (!isObject(input)) return void 0;
|
|
219
|
+
const { text: text2, bold, italic, href } = input;
|
|
220
|
+
const hasValidMarks = typeof text2 === "string" && (bold === void 0 || bold === true) && (italic === void 0 || italic === true) && (href === void 0 || typeof href === "string");
|
|
221
|
+
if (!hasValidMarks) return void 0;
|
|
222
|
+
return {
|
|
223
|
+
text: text2,
|
|
224
|
+
...bold === true ? { bold } : {},
|
|
225
|
+
...italic === true ? { italic } : {},
|
|
226
|
+
...typeof href === "string" ? { href } : {}
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function haveSameMarks(first, second) {
|
|
230
|
+
return first.bold === second.bold && first.italic === second.italic && first.href === second.href;
|
|
231
|
+
}
|
|
232
|
+
function hasWords(block) {
|
|
233
|
+
return block.kind === "paragraph" ? block.spans.length > 0 : block.items.length > 0;
|
|
234
|
+
}
|
|
235
|
+
function linesOf(text2) {
|
|
236
|
+
return text2.flatMap(
|
|
237
|
+
(block) => block.kind === "paragraph" ? [block.spans] : block.items
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
function plainBlockOf(block) {
|
|
241
|
+
return block.kind === "paragraph" ? plainLineOf(block.spans) : block.items.map(plainLineOf).join(LINE_SEPARATOR);
|
|
242
|
+
}
|
|
243
|
+
function plainLineOf(line) {
|
|
244
|
+
return line.map((span) => span.text).join("");
|
|
245
|
+
}
|
|
246
|
+
function isObject(value) {
|
|
247
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
248
|
+
}
|
|
249
|
+
|
|
150
250
|
// src/schema/record-ids.ts
|
|
151
251
|
var RECORD_ID_KEY = "id";
|
|
152
252
|
var RECORD_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/u;
|
|
@@ -240,6 +340,7 @@ function issuesInField(field, value, path, idsOf) {
|
|
|
240
340
|
(record, index) => issuesInFields(field.item, record, [...path, index], idsOf)
|
|
241
341
|
);
|
|
242
342
|
case "text":
|
|
343
|
+
case "richText":
|
|
243
344
|
case "number":
|
|
244
345
|
case "date":
|
|
245
346
|
case "image":
|
|
@@ -312,6 +413,8 @@ function parseField(field, input, path) {
|
|
|
312
413
|
switch (field.kind) {
|
|
313
414
|
case "text":
|
|
314
415
|
return parseText(field, input, path);
|
|
416
|
+
case "richText":
|
|
417
|
+
return parseRichText(field, input, path);
|
|
315
418
|
case "number":
|
|
316
419
|
return parseNumber(field, input, path);
|
|
317
420
|
case "date":
|
|
@@ -353,6 +456,24 @@ function parseText(field, input, path) {
|
|
|
353
456
|
}
|
|
354
457
|
return valid(input);
|
|
355
458
|
}
|
|
459
|
+
function parseRichText(field, input, path) {
|
|
460
|
+
const read = typeof input === "string" ? richTextOf(input) : readRichText(input);
|
|
461
|
+
if (read === void 0) {
|
|
462
|
+
return invalidType(defaultValue(field), path);
|
|
463
|
+
}
|
|
464
|
+
const text2 = field.inline === true ? asOneParagraph(read) : read;
|
|
465
|
+
const hasUnsupportedLink = linkAddressesOf(text2).some(
|
|
466
|
+
(href) => linkTargetOf(href) === void 0
|
|
467
|
+
);
|
|
468
|
+
const linkIssues = hasUnsupportedLink ? [{ path, code: "unsupported-link-href" }] : [];
|
|
469
|
+
const lengthIssues = tooLongIssues(field.maxLength, plainTextOf(text2), path);
|
|
470
|
+
return { value: text2, issues: [...linkIssues, ...lengthIssues] };
|
|
471
|
+
}
|
|
472
|
+
function tooLongIssues(maxLength, text2, path) {
|
|
473
|
+
if (maxLength === void 0) return [];
|
|
474
|
+
const isTooLong = countCharacters(text2) > maxLength;
|
|
475
|
+
return isTooLong ? [{ path, code: "too-long", maxLength }] : [];
|
|
476
|
+
}
|
|
356
477
|
function parseNumber(field, input, path) {
|
|
357
478
|
if (input === null) {
|
|
358
479
|
return valid(null);
|
|
@@ -668,6 +789,7 @@ function openingHoursField(options = {}) {
|
|
|
668
789
|
export {
|
|
669
790
|
defineSchema,
|
|
670
791
|
text,
|
|
792
|
+
richText,
|
|
671
793
|
number,
|
|
672
794
|
date,
|
|
673
795
|
image,
|
|
@@ -685,6 +807,11 @@ export {
|
|
|
685
807
|
defaultContent,
|
|
686
808
|
linkTargetOf,
|
|
687
809
|
hrefOf,
|
|
810
|
+
richTextOf,
|
|
811
|
+
plainTextOf,
|
|
812
|
+
asOneParagraph,
|
|
813
|
+
readRichText,
|
|
814
|
+
normalizedLine,
|
|
688
815
|
RECORD_ID_KEY,
|
|
689
816
|
isRecordId,
|
|
690
817
|
newRecord,
|
|
@@ -6,6 +6,18 @@ interface TextField {
|
|
|
6
6
|
/** In characters as people see them (see countCharacters), not UTF-16 units. */
|
|
7
7
|
readonly maxLength?: number;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* A text with paragraphs, lists, bold, italic and links inside it: a paragraph with a link in a
|
|
11
|
+
* sentence stays one field. `inline` keeps it one paragraph without lists, for a text inside an
|
|
12
|
+
* element that holds one line of words.
|
|
13
|
+
*/
|
|
14
|
+
interface RichTextField {
|
|
15
|
+
readonly kind: "richText";
|
|
16
|
+
readonly label: string;
|
|
17
|
+
readonly inline?: boolean;
|
|
18
|
+
/** In characters of its words as people see them, without the marks. */
|
|
19
|
+
readonly maxLength?: number;
|
|
20
|
+
}
|
|
9
21
|
interface NumberField {
|
|
10
22
|
readonly kind: "number";
|
|
11
23
|
readonly label: string;
|
|
@@ -96,7 +108,7 @@ interface CollectionField<F extends RecordFields = RecordFields> {
|
|
|
96
108
|
/** The field of a record that names it in the editor: a text field, or a link by its text. */
|
|
97
109
|
readonly itemTitle?: keyof F & string;
|
|
98
110
|
}
|
|
99
|
-
type Field = TextField | NumberField | DateField | ImageField | LinkField | ToggleField | ChoiceField | ChoicesField | UrlField | TimeField | ReferenceField | ReferencesField | GroupField | CollectionField;
|
|
111
|
+
type Field = TextField | RichTextField | NumberField | DateField | ImageField | LinkField | ToggleField | ChoiceField | ChoicesField | UrlField | TimeField | ReferenceField | ReferencesField | GroupField | CollectionField;
|
|
100
112
|
type FieldKind = Field["kind"];
|
|
101
113
|
/** Field names to fields; the order of the keys is the order of the form. */
|
|
102
114
|
interface Fields {
|
|
@@ -110,6 +122,7 @@ type FieldOptions<F extends Field> = Omit<F, "kind">;
|
|
|
110
122
|
/** The root of a site's schema. Only checks the shape and keeps the literal types. */
|
|
111
123
|
declare function defineSchema<F extends Fields>(fields: F): F;
|
|
112
124
|
declare function text(options: FieldOptions<TextField>): TextField;
|
|
125
|
+
declare function richText(options: FieldOptions<RichTextField>): RichTextField;
|
|
113
126
|
declare function number(options: FieldOptions<NumberField>): NumberField;
|
|
114
127
|
declare function date(options: FieldOptions<DateField>): DateField;
|
|
115
128
|
declare function image(options: FieldOptions<ImageField>): ImageField;
|
|
@@ -125,6 +138,37 @@ declare function references(options: FieldOptions<ReferencesField>): ReferencesF
|
|
|
125
138
|
declare function group<F extends Fields>(options: FieldOptions<GroupField<F>>): GroupField<F>;
|
|
126
139
|
declare function collection<F extends RecordFields>(options: FieldOptions<CollectionField<F>>): CollectionField<F>;
|
|
127
140
|
|
|
141
|
+
/** A piece of a text with its marks; a link is a piece with an address. */
|
|
142
|
+
interface RichSpan {
|
|
143
|
+
readonly text: string;
|
|
144
|
+
readonly bold?: true;
|
|
145
|
+
readonly italic?: true;
|
|
146
|
+
/** A path of the site, a web address, `tel:` or `mailto:`; see linkTargetOf. */
|
|
147
|
+
readonly href?: string;
|
|
148
|
+
}
|
|
149
|
+
type RichLine = readonly RichSpan[];
|
|
150
|
+
type RichBlock = {
|
|
151
|
+
readonly kind: "paragraph";
|
|
152
|
+
readonly spans: RichLine;
|
|
153
|
+
} | {
|
|
154
|
+
readonly kind: "list";
|
|
155
|
+
readonly items: readonly RichLine[];
|
|
156
|
+
};
|
|
157
|
+
type RichText = readonly RichBlock[];
|
|
158
|
+
/** A plain text as paragraphs: how a text field becomes formatted text and keeps its words. */
|
|
159
|
+
declare function richTextOf(plain: string): RichText;
|
|
160
|
+
/** The words of a text without its marks: for a length, a search, a summary. */
|
|
161
|
+
declare function plainTextOf(text: RichText): string;
|
|
162
|
+
/** One paragraph of all the text: a text that stands inside a sentence-level element. */
|
|
163
|
+
declare function asOneParagraph(text: RichText): RichText;
|
|
164
|
+
/**
|
|
165
|
+
* Formatted text read from any input, or undefined when it is not one: the same text gives the
|
|
166
|
+
* same value, with empty pieces left out and neighbors with the same marks joined.
|
|
167
|
+
*/
|
|
168
|
+
declare function readRichText(input: unknown): RichText | undefined;
|
|
169
|
+
/** The same line with empty pieces left out and neighbors with the same marks joined. */
|
|
170
|
+
declare function normalizedLine(spans: readonly RichSpan[]): RichLine;
|
|
171
|
+
|
|
128
172
|
/** The point of a photo that must stay in view when a site crops it: 0 to 1 from the left and the top. */
|
|
129
173
|
interface ImageFocus {
|
|
130
174
|
readonly x: number;
|
|
@@ -145,7 +189,7 @@ interface LinkValue {
|
|
|
145
189
|
* The value of each field. A text can be empty (""), the other scalar fields can be unset (null):
|
|
146
190
|
* content is filled in by people, so a site must be ready for a missing price or date.
|
|
147
191
|
*/
|
|
148
|
-
type ValueOf<F extends Field> = F extends TextField ? string : F extends NumberField ? number | null : F extends DateField ? string | null : F extends ImageField ? ImageValue | null : F extends LinkField ? LinkValue | null : F extends ToggleField ? boolean : F extends ChoiceField<infer Options> ? OptionValue<Options> | null : F extends ChoicesField<infer Options> ? readonly OptionValue<Options>[] : F extends UrlField ? string | null : F extends TimeField ? string | null : F extends ReferenceField ? string | null : F extends ReferencesField ? readonly string[] : F extends GroupField<infer Group> ? ContentOf<Group> : F extends CollectionField<infer Item> ? readonly RecordOf<Item>[] : never;
|
|
192
|
+
type ValueOf<F extends Field> = F extends TextField ? string : F extends RichTextField ? RichText : F extends NumberField ? number | null : F extends DateField ? string | null : F extends ImageField ? ImageValue | null : F extends LinkField ? LinkValue | null : F extends ToggleField ? boolean : F extends ChoiceField<infer Options> ? OptionValue<Options> | null : F extends ChoicesField<infer Options> ? readonly OptionValue<Options>[] : F extends UrlField ? string | null : F extends TimeField ? string | null : F extends ReferenceField ? string | null : F extends ReferencesField ? readonly string[] : F extends GroupField<infer Group> ? ContentOf<Group> : F extends CollectionField<infer Item> ? readonly RecordOf<Item>[] : never;
|
|
149
193
|
/**
|
|
150
194
|
* A record of a collection: its fields and its id. The id is missing only in content no editor has
|
|
151
195
|
* saved yet, such as a site's initial content (see withRecordIds).
|
|
@@ -163,8 +207,8 @@ type ContentOf<F extends Fields> = {
|
|
|
163
207
|
interface Content {
|
|
164
208
|
readonly [name: string]: FieldValue;
|
|
165
209
|
}
|
|
166
|
-
type FieldValue = string | number | boolean | null | readonly string[] | ImageValue | LinkValue | Content | readonly Content[];
|
|
210
|
+
type FieldValue = string | number | boolean | null | readonly string[] | ImageValue | LinkValue | RichText | Content | readonly Content[];
|
|
167
211
|
declare function defaultValue(field: Field): FieldValue;
|
|
168
212
|
declare function defaultContent(fields: Fields): Content;
|
|
169
213
|
|
|
170
|
-
export {
|
|
214
|
+
export { time as $, defaultContent as A, defaultValue as B, type ContentOf as C, type DateField as D, defineSchema as E, type Fields as F, type GroupField as G, group as H, type ImageField as I, image as J, link as K, type LinkValue as L, normalizedLine as M, type NumberField as N, type OptionValue as O, number as P, plainTextOf as Q, type RichText as R, readRichText as S, type TextField as T, type UrlField as U, type ValueOf as V, reference as W, references as X, richText as Y, richTextOf as Z, text as _, type Content as a, toggle as a0, url as a1, type ImageValue as b, type Field as c, type CollectionField as d, type RecordFields as e, type LinkField as f, type ChoicesField as g, type TimeField as h, type ChoiceField as i, type ChoiceOption as j, type FieldKind as k, type FieldValue as l, type ImageFocus as m, type RecordOf as n, type ReferenceField as o, type ReferencesField as p, type RichBlock as q, type RichLine as r, type RichSpan as s, type RichTextField as t, type ToggleField as u, asOneParagraph as v, choice as w, choices as x, collection as y, date as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { F as Fields, a as Content } from './content-
|
|
2
|
-
import { F as FieldPath } from './parse-content-
|
|
1
|
+
import { R as RichText, F as Fields, a as Content } from './content-6k-E7NWf.js';
|
|
2
|
+
import { F as FieldPath } from './parse-content-C9ldnmvj.js';
|
|
3
3
|
|
|
4
4
|
interface Box {
|
|
5
5
|
readonly top: number;
|
|
@@ -17,12 +17,53 @@ declare function shortcutOf(event: KeyboardEvent): Shortcut | undefined;
|
|
|
17
17
|
|
|
18
18
|
type InlineEditingOutcome = "kept" | "reverted";
|
|
19
19
|
|
|
20
|
+
interface TextPoint {
|
|
21
|
+
/** The paragraph or the list item, counted from the start of the text. */
|
|
22
|
+
readonly line: number;
|
|
23
|
+
/** Characters from the start of the line; a line break is one character. */
|
|
24
|
+
readonly offset: number;
|
|
25
|
+
}
|
|
26
|
+
interface TextSelection {
|
|
27
|
+
readonly start: TextPoint;
|
|
28
|
+
readonly end: TextPoint;
|
|
29
|
+
}
|
|
30
|
+
type Mark = "bold" | "italic";
|
|
31
|
+
/** What the selected words have, or the words at the cursor when nothing is selected. */
|
|
32
|
+
interface TextFormats {
|
|
33
|
+
readonly isBold: boolean;
|
|
34
|
+
readonly isItalic: boolean;
|
|
35
|
+
readonly isList: boolean;
|
|
36
|
+
/** The address of the link the selection is in, when all of it is in one link. */
|
|
37
|
+
readonly href: string | undefined;
|
|
38
|
+
}
|
|
39
|
+
/** Whether the selection holds no characters: it is a cursor. */
|
|
40
|
+
declare function isCollapsed(selection: TextSelection): boolean;
|
|
41
|
+
/** The marks every selected word has, and the link they are in. */
|
|
42
|
+
declare function formatsAt(text: RichText, selection: TextSelection): TextFormats;
|
|
43
|
+
/** The words of the link the cursor is in, or undefined outside a link. */
|
|
44
|
+
declare function linkSelectionAt(text: RichText, point: TextPoint): TextSelection | undefined;
|
|
45
|
+
/** The mark on every selected word, or off them all when every one has it already. */
|
|
46
|
+
declare function toggleMark(text: RichText, selection: TextSelection, mark: Mark): RichText;
|
|
47
|
+
/** The selected words lead to the address, or lead nowhere when it is undefined. */
|
|
48
|
+
declare function setLink(text: RichText, selection: TextSelection, href: string | undefined): RichText;
|
|
49
|
+
/** The selected lines become a list, or paragraphs again when they all are a list already. */
|
|
50
|
+
declare function toggleList(text: RichText, selection: TextSelection): RichText;
|
|
51
|
+
|
|
52
|
+
/** A change of formatting the editor's toolbar asks for. */
|
|
53
|
+
type TextFormat = "bold" | "italic" | "list";
|
|
54
|
+
/** The selection in the typed text: where it is on the page and what its words have. */
|
|
55
|
+
interface TypedSelection {
|
|
56
|
+
readonly box: Box;
|
|
57
|
+
readonly isCollapsed: boolean;
|
|
58
|
+
readonly formats: TextFormats;
|
|
59
|
+
}
|
|
60
|
+
|
|
20
61
|
/**
|
|
21
62
|
* The version of what the two say to each other. A site updates @seamlet/astro when it likes, so the
|
|
22
63
|
* editor may meet a bridge of another version: it tells by this number, said with `ready`, instead
|
|
23
64
|
* of misreading the page. Raised whenever a message changes in a way the other side cannot read.
|
|
24
65
|
*/
|
|
25
|
-
declare const PROTOCOL_VERSION =
|
|
66
|
+
declare const PROTOCOL_VERSION = 2;
|
|
26
67
|
interface Point {
|
|
27
68
|
readonly x: number;
|
|
28
69
|
readonly y: number;
|
|
@@ -99,6 +140,18 @@ type PageMessage =
|
|
|
99
140
|
readonly type: "typed";
|
|
100
141
|
readonly path: string;
|
|
101
142
|
readonly text: string;
|
|
143
|
+
}
|
|
144
|
+
/** The formatted text typed in place, after every character and every change of its marks. */
|
|
145
|
+
| {
|
|
146
|
+
readonly type: "rich-typed";
|
|
147
|
+
readonly path: string;
|
|
148
|
+
readonly text: RichText;
|
|
149
|
+
}
|
|
150
|
+
/** Where the selection in the typed formatted text is now, for the editor's toolbar. */
|
|
151
|
+
| {
|
|
152
|
+
readonly type: "typed-selection";
|
|
153
|
+
readonly path: string;
|
|
154
|
+
readonly selection: TypedSelection | undefined;
|
|
102
155
|
} | {
|
|
103
156
|
readonly type: "typing-ended";
|
|
104
157
|
readonly path: string;
|
|
@@ -127,6 +180,25 @@ type EditorMessage =
|
|
|
127
180
|
readonly text: string;
|
|
128
181
|
readonly isSingleLine: boolean;
|
|
129
182
|
readonly point: Point;
|
|
183
|
+
}
|
|
184
|
+
/** Type the formatted text of the field in its element, if the element shows it as it is. */
|
|
185
|
+
| {
|
|
186
|
+
readonly type: "start-rich-typing";
|
|
187
|
+
readonly path: string;
|
|
188
|
+
readonly text: RichText;
|
|
189
|
+
/** The words alone, in an element of one line. */
|
|
190
|
+
readonly isInline: boolean;
|
|
191
|
+
readonly point: Point;
|
|
192
|
+
}
|
|
193
|
+
/** Mark the selected words of the formatted text typed in place, or make its lines a list. */
|
|
194
|
+
| {
|
|
195
|
+
readonly type: "format-typed";
|
|
196
|
+
readonly format: TextFormat;
|
|
197
|
+
}
|
|
198
|
+
/** The selected words of the typed text, or the link at the cursor, lead here, or nowhere. */
|
|
199
|
+
| {
|
|
200
|
+
readonly type: "link-typed";
|
|
201
|
+
readonly href: string | undefined;
|
|
130
202
|
} | {
|
|
131
203
|
readonly type: "stop-typing";
|
|
132
204
|
}
|
|
@@ -140,4 +212,4 @@ declare function readPageMessage(data: unknown): PageMessage | undefined;
|
|
|
140
212
|
/** The message the editor sent, or undefined for anything that is not one. */
|
|
141
213
|
declare function readEditorMessage(data: unknown): EditorMessage | undefined;
|
|
142
214
|
|
|
143
|
-
export { type Box as B, type EditorMessage as E, type InlineEditingOutcome as I, type LinkBox as L, type
|
|
215
|
+
export { type Box as B, type EditorMessage as E, type InlineEditingOutcome as I, type LinkBox as L, type Mark as M, type PageMessage as P, type Shortcut as S, type TextSelection as T, type Viewport as V, type EditorKey as a, type MarkerBox as b, PROTOCOL_VERSION as c, type PageLayout as d, type Point as e, type TextFormat as f, type TextFormats as g, type TextPoint as h, type TypedSelection as i, formatsAt as j, isCollapsed as k, linkSelectionAt as l, readPageMessage as m, shortcutOf as n, toggleMark as o, readEditorMessage as r, setLink as s, toggleList as t };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { F as Fields, C as ContentOf } from './content-
|
|
1
|
+
import { F as Fields, C as ContentOf } from './content-6k-E7NWf.js';
|
|
2
2
|
|
|
3
3
|
/** Where a value lives in the content: field names and, inside a collection, record indexes. */
|
|
4
4
|
type FieldPath = readonly (string | number)[];
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import { F as
|
|
1
|
+
import { T as TextSelection } from './messages-Dx0jNy3N.js';
|
|
2
|
+
export { B as Box, a as EditorKey, E as EditorMessage, I as InlineEditingOutcome, L as LinkBox, M as Mark, b as MarkerBox, c as PROTOCOL_VERSION, d as PageLayout, P as PageMessage, e as Point, S as Shortcut, f as TextFormat, g as TextFormats, h as TextPoint, i as TypedSelection, V as Viewport, j as formatsAt, k as isCollapsed, l as linkSelectionAt, r as readEditorMessage, m as readPageMessage, s as setLink, n as shortcutOf, t as toggleList, o as toggleMark } from './messages-Dx0jNy3N.js';
|
|
3
|
+
import { F as Fields, I as ImageField, R as RichText } from './content-6k-E7NWf.js';
|
|
4
|
+
import { F as FieldPath } from './parse-content-C9ldnmvj.js';
|
|
4
5
|
|
|
5
6
|
declare function carriesFiles(event: DragEvent): boolean;
|
|
6
7
|
|
|
@@ -16,6 +17,17 @@ declare function imageFieldAt(schema: Fields, path: string | undefined): {
|
|
|
16
17
|
*/
|
|
17
18
|
declare function closestMarkedPath(path: FieldPath, isMarked: (path: string) => boolean): string | undefined;
|
|
18
19
|
|
|
20
|
+
/** The elements of a text, put into the editable element in place of what it held. */
|
|
21
|
+
declare function renderRichText(element: HTMLElement, text: RichText): void;
|
|
22
|
+
/** What the editable element holds now, as formatted text. */
|
|
23
|
+
declare function readRichTextFrom(element: HTMLElement): RichText;
|
|
24
|
+
/** Where the selection is in the text of the element, or undefined when it is elsewhere. */
|
|
25
|
+
declare function readSelectionFrom(element: HTMLElement): TextSelection | undefined;
|
|
26
|
+
/** Puts the selection on the text of an element this module rendered. */
|
|
27
|
+
declare function selectIn(element: HTMLElement, selection: TextSelection): void;
|
|
28
|
+
/** Puts plain words in place of the selection, their line breaks as `<br>`, the cursor after them. */
|
|
29
|
+
declare function insertPlainText(element: HTMLElement, words: string): void;
|
|
30
|
+
|
|
19
31
|
/** Where a site hands out its own photos: `/seamlet-photos/menu/cafe/01.jpg`. */
|
|
20
32
|
declare const OWN_PHOTOS_PATH = "/seamlet-photos";
|
|
21
33
|
/** An address of the site itself that is not an upload, and that cannot climb out of the site. */
|
|
@@ -23,4 +35,4 @@ declare function isOwnPhotoSrc(src: string): boolean;
|
|
|
23
35
|
/** Where the site hands out its own photo; undefined for an upload or another site's address. */
|
|
24
36
|
declare function ownPhotoPath(src: string): string | undefined;
|
|
25
37
|
|
|
26
|
-
export { OWN_PHOTOS_PATH, carriesFiles, closestMarkedPath, imageFieldAt, isOwnPhotoSrc, ownPhotoPath };
|
|
38
|
+
export { OWN_PHOTOS_PATH, TextSelection, carriesFiles, closestMarkedPath, imageFieldAt, insertPlainText, isOwnPhotoSrc, ownPhotoPath, readRichTextFrom, readSelectionFrom, renderRichText, selectIn };
|
package/dist/protocol.js
CHANGED
|
@@ -7,21 +7,43 @@ import {
|
|
|
7
7
|
PROTOCOL_VERSION,
|
|
8
8
|
carriesFiles,
|
|
9
9
|
closestMarkedPath,
|
|
10
|
+
formatsAt,
|
|
10
11
|
imageFieldAt,
|
|
12
|
+
insertPlainText,
|
|
13
|
+
isCollapsed,
|
|
14
|
+
linkSelectionAt,
|
|
11
15
|
readEditorMessage,
|
|
12
16
|
readPageMessage,
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
readRichTextFrom,
|
|
18
|
+
readSelectionFrom,
|
|
19
|
+
renderRichText,
|
|
20
|
+
selectIn,
|
|
21
|
+
setLink,
|
|
22
|
+
shortcutOf,
|
|
23
|
+
toggleList,
|
|
24
|
+
toggleMark
|
|
25
|
+
} from "./chunk-27XIZEVS.js";
|
|
26
|
+
import "./chunk-ZUJEM3P7.js";
|
|
16
27
|
export {
|
|
17
28
|
OWN_PHOTOS_PATH,
|
|
18
29
|
PROTOCOL_VERSION,
|
|
19
30
|
carriesFiles,
|
|
20
31
|
closestMarkedPath,
|
|
32
|
+
formatsAt,
|
|
21
33
|
imageFieldAt,
|
|
34
|
+
insertPlainText,
|
|
35
|
+
isCollapsed,
|
|
22
36
|
isOwnPhotoSrc,
|
|
37
|
+
linkSelectionAt,
|
|
23
38
|
ownPhotoPath,
|
|
24
39
|
readEditorMessage,
|
|
25
40
|
readPageMessage,
|
|
26
|
-
|
|
41
|
+
readRichTextFrom,
|
|
42
|
+
readSelectionFrom,
|
|
43
|
+
renderRichText,
|
|
44
|
+
selectIn,
|
|
45
|
+
setLink,
|
|
46
|
+
shortcutOf,
|
|
47
|
+
toggleList,
|
|
48
|
+
toggleMark
|
|
27
49
|
};
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { b as ImageValue, L as LinkValue, c as Field, d as CollectionField, F as Fields, a as Content,
|
|
2
|
-
export {
|
|
3
|
-
import { F as FieldPath } from './parse-content-
|
|
4
|
-
export { C as ContentIssue, P as ParsedContent, c as countCharacters, f as formatFieldPath, p as parseContent } from './parse-content-
|
|
1
|
+
import { b as ImageValue, L as LinkValue, c as Field, d as CollectionField, F as Fields, a as Content, e as RecordFields, C as ContentOf, G as GroupField, f as LinkField, T as TextField, U as UrlField, g as ChoicesField, h as TimeField, I as ImageField } from './content-6k-E7NWf.js';
|
|
2
|
+
export { i as ChoiceField, j as ChoiceOption, D as DateField, k as FieldKind, l as FieldValue, m as ImageFocus, N as NumberField, O as OptionValue, n as RecordOf, o as ReferenceField, p as ReferencesField, q as RichBlock, r as RichLine, s as RichSpan, R as RichText, t as RichTextField, u as ToggleField, V as ValueOf, v as asOneParagraph, w as choice, x as choices, y as collection, z as date, A as defaultContent, B as defaultValue, E as defineSchema, H as group, J as image, K as link, M as normalizedLine, P as number, Q as plainTextOf, S as readRichText, W as reference, X as references, Y as richText, Z as richTextOf, _ as text, $ as time, a0 as toggle, a1 as url } from './content-6k-E7NWf.js';
|
|
3
|
+
import { F as FieldPath } from './parse-content-C9ldnmvj.js';
|
|
4
|
+
export { C as ContentIssue, P as ParsedContent, c as countCharacters, f as formatFieldPath, p as parseContent } from './parse-content-C9ldnmvj.js';
|
|
5
5
|
|
|
6
6
|
declare const FIELD_PATH_ATTRIBUTE = "data-cms-path";
|
|
7
7
|
interface FieldMarker {
|
package/dist/schema.js
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
REVEAL_ATTRIBUTE,
|
|
6
6
|
REVEAL_EVENT,
|
|
7
7
|
WEEKDAYS,
|
|
8
|
+
asOneParagraph,
|
|
8
9
|
choice,
|
|
9
10
|
choices,
|
|
10
11
|
collection,
|
|
@@ -26,19 +27,24 @@ import {
|
|
|
26
27
|
link,
|
|
27
28
|
linkTargetOf,
|
|
28
29
|
newRecord,
|
|
30
|
+
normalizedLine,
|
|
29
31
|
number,
|
|
30
32
|
openingHoursField,
|
|
31
33
|
parseContent,
|
|
34
|
+
plainTextOf,
|
|
35
|
+
readRichText,
|
|
32
36
|
reference,
|
|
33
37
|
references,
|
|
34
38
|
resolveFieldPath,
|
|
39
|
+
richText,
|
|
40
|
+
richTextOf,
|
|
35
41
|
seoFields,
|
|
36
42
|
text,
|
|
37
43
|
time,
|
|
38
44
|
toggle,
|
|
39
45
|
url,
|
|
40
46
|
withRecordIds
|
|
41
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-ZUJEM3P7.js";
|
|
42
48
|
export {
|
|
43
49
|
FIELD_PATH_ATTRIBUTE,
|
|
44
50
|
RECORD_ID_KEY,
|
|
@@ -46,6 +52,7 @@ export {
|
|
|
46
52
|
REVEAL_ATTRIBUTE,
|
|
47
53
|
REVEAL_EVENT,
|
|
48
54
|
WEEKDAYS,
|
|
55
|
+
asOneParagraph,
|
|
49
56
|
choice,
|
|
50
57
|
choices,
|
|
51
58
|
collection,
|
|
@@ -67,12 +74,17 @@ export {
|
|
|
67
74
|
link,
|
|
68
75
|
linkTargetOf,
|
|
69
76
|
newRecord,
|
|
77
|
+
normalizedLine,
|
|
70
78
|
number,
|
|
71
79
|
openingHoursField,
|
|
72
80
|
parseContent,
|
|
81
|
+
plainTextOf,
|
|
82
|
+
readRichText,
|
|
73
83
|
reference,
|
|
74
84
|
references,
|
|
75
85
|
resolveFieldPath,
|
|
86
|
+
richText,
|
|
87
|
+
richTextOf,
|
|
76
88
|
seoFields,
|
|
77
89
|
text,
|
|
78
90
|
time,
|
package/dist/site.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ImageMetadata } from 'astro';
|
|
2
2
|
import { AstroComponentFactory } from 'astro/runtime/server/index.js';
|
|
3
|
-
import { F as Fields, C as ContentOf } from './content-
|
|
3
|
+
import { F as Fields, C as ContentOf } from './content-6k-E7NWf.js';
|
|
4
4
|
|
|
5
5
|
interface SeamletSiteDefinition<F extends Fields> {
|
|
6
6
|
/** The site's address in the CMS: `/sites/<id>`. */
|
package/dist/site.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seamlet/astro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.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",
|
|
@@ -46,11 +46,13 @@
|
|
|
46
46
|
"./routes/own-photos": {
|
|
47
47
|
"types": "./dist/routes/own-photos.d.ts",
|
|
48
48
|
"default": "./dist/routes/own-photos.js"
|
|
49
|
-
}
|
|
49
|
+
},
|
|
50
|
+
"./components/RichText.astro": "./components/RichText.astro"
|
|
50
51
|
},
|
|
51
52
|
"files": [
|
|
52
53
|
"dist",
|
|
53
|
-
"routes"
|
|
54
|
+
"routes",
|
|
55
|
+
"components"
|
|
54
56
|
],
|
|
55
57
|
"scripts": {
|
|
56
58
|
"build": "tsup"
|