@openbrf/plugin-sdk 0.0.0-stage → 1.2.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/LICENSE +661 -0
- package/LICENSE-EXCEPTION.md +28 -0
- package/README.md +94 -2
- package/dist/abort-signal.d.ts +23 -0
- package/dist/abort-signal.d.ts.map +1 -0
- package/dist/abort-signal.js +2 -0
- package/dist/abort-signal.js.map +1 -0
- package/dist/action-refusal.d.ts +101 -0
- package/dist/action-refusal.d.ts.map +1 -0
- package/dist/action-refusal.js +96 -0
- package/dist/action-refusal.js.map +1 -0
- package/dist/action-schema.d.ts +42 -0
- package/dist/action-schema.d.ts.map +1 -0
- package/dist/action-schema.js +67 -0
- package/dist/action-schema.js.map +1 -0
- package/dist/actions.d.ts +287 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +68 -0
- package/dist/actions.js.map +1 -0
- package/dist/api-version.d.ts +23 -0
- package/dist/api-version.d.ts.map +1 -0
- package/dist/api-version.js +27 -0
- package/dist/api-version.js.map +1 -0
- package/dist/blocks.d.ts +310 -0
- package/dist/blocks.d.ts.map +1 -0
- package/dist/blocks.js +185 -0
- package/dist/blocks.js.map +1 -0
- package/dist/catalog.d.ts +707 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +567 -0
- package/dist/catalog.js.map +1 -0
- package/dist/define-plugin.d.ts +14 -0
- package/dist/define-plugin.d.ts.map +1 -0
- package/dist/define-plugin.js +15 -0
- package/dist/define-plugin.js.map +1 -0
- package/dist/entitlements.d.ts +117 -0
- package/dist/entitlements.d.ts.map +1 -0
- package/dist/entitlements.js +62 -0
- package/dist/entitlements.js.map +1 -0
- package/dist/extensions.d.ts +183 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +67 -0
- package/dist/extensions.js.map +1 -0
- package/dist/finances.d.ts +294 -0
- package/dist/finances.d.ts.map +1 -0
- package/dist/finances.js +56 -0
- package/dist/finances.js.map +1 -0
- package/dist/findings.d.ts +156 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +146 -0
- package/dist/findings.js.map +1 -0
- package/dist/host.d.ts +827 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +80 -0
- package/dist/host.js.map +1 -0
- package/dist/imports.d.ts +104 -0
- package/dist/imports.d.ts.map +1 -0
- package/dist/imports.js +70 -0
- package/dist/imports.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/integrity.d.ts +38 -0
- package/dist/integrity.d.ts.map +1 -0
- package/dist/integrity.js +105 -0
- package/dist/integrity.js.map +1 -0
- package/dist/localized-text.d.ts +18 -0
- package/dist/localized-text.d.ts.map +1 -0
- package/dist/localized-text.js +17 -0
- package/dist/localized-text.js.map +1 -0
- package/dist/manifest.d.ts +1122 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +1118 -0
- package/dist/manifest.js.map +1 -0
- package/dist/module.d.ts +35 -0
- package/dist/module.d.ts.map +1 -0
- package/dist/module.js +2 -0
- package/dist/module.js.map +1 -0
- package/dist/package-check.d.ts +66 -0
- package/dist/package-check.d.ts.map +1 -0
- package/dist/package-check.js +755 -0
- package/dist/package-check.js.map +1 -0
- package/dist/permissions.d.ts +224 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +277 -0
- package/dist/permissions.js.map +1 -0
- package/dist/recipients.d.ts +139 -0
- package/dist/recipients.d.ts.map +1 -0
- package/dist/recipients.js +223 -0
- package/dist/recipients.js.map +1 -0
- package/dist/records.d.ts +130 -0
- package/dist/records.d.ts.map +1 -0
- package/dist/records.js +85 -0
- package/dist/records.js.map +1 -0
- package/dist/require-capability.d.ts +37 -0
- package/dist/require-capability.d.ts.map +1 -0
- package/dist/require-capability.js +88 -0
- package/dist/require-capability.js.map +1 -0
- package/dist/settings-schema.d.ts +130 -0
- package/dist/settings-schema.d.ts.map +1 -0
- package/dist/settings-schema.js +272 -0
- package/dist/settings-schema.js.map +1 -0
- package/dist/standard-schema.d.ts +43 -0
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js +2 -0
- package/dist/standard-schema.js.map +1 -0
- package/package.json +55 -3
- package/src/abort-signal.ts +22 -0
- package/src/action-refusal.ts +178 -0
- package/src/action-schema.ts +89 -0
- package/src/actions.ts +344 -0
- package/src/api-version.ts +28 -0
- package/src/blocks.ts +289 -0
- package/src/catalog.ts +679 -0
- package/src/define-plugin.ts +18 -0
- package/src/entitlements.ts +150 -0
- package/src/extensions.ts +212 -0
- package/src/finances.ts +317 -0
- package/src/findings.ts +163 -0
- package/src/host.ts +894 -0
- package/src/imports.ts +135 -0
- package/src/index.ts +316 -0
- package/src/integrity.ts +125 -0
- package/src/localized-text.ts +19 -0
- package/src/manifest.ts +1412 -0
- package/src/module.ts +38 -0
- package/src/package-check.ts +894 -0
- package/src/permissions.ts +295 -0
- package/src/recipients.ts +294 -0
- package/src/records.ts +172 -0
- package/src/require-capability.ts +106 -0
- package/src/settings-schema.ts +334 -0
- package/src/standard-schema.ts +39 -0
package/dist/blocks.d.ts
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { PluginAbortSignal } from "./abort-signal.ts";
|
|
3
|
+
import type { PluginSettingsValues } from "./settings-schema.ts";
|
|
4
|
+
/**
|
|
5
|
+
* Blocks a plugin adds to the association's website.
|
|
6
|
+
*
|
|
7
|
+
* A page on the website is a list of blocks, never markup (ADR 0006), and a
|
|
8
|
+
* plugin's block is one more type in that list. The manifest declares it - its
|
|
9
|
+
* name, how the page editor offers it and the settings the board fills in - and
|
|
10
|
+
* the server bundle registers the function that renders it. The host does the
|
|
11
|
+
* rest: it offers the block in the editor, validates the settings on every
|
|
12
|
+
* save, calls the render function while it renders the page, and decides what
|
|
13
|
+
* of the answer reaches the visitor's browser.
|
|
14
|
+
*
|
|
15
|
+
* What the render function returns is a small tree of elements rather than a
|
|
16
|
+
* string of HTML. The host reads it against a short list of elements and
|
|
17
|
+
* attributes and prints what passes through the same renderer as the rest of
|
|
18
|
+
* the page, so a script, a stylesheet, an event handler or a picture from
|
|
19
|
+
* another host has no way into the markup however the tree was built. The
|
|
20
|
+
* website's content security policy refuses all four as well; the list is what
|
|
21
|
+
* keeps the page from carrying them at all.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* The name of one block, unique within its plugin.
|
|
25
|
+
*
|
|
26
|
+
* The block's type id is composed by the host as `<plugin id>/<name>`, which is
|
|
27
|
+
* what a page stores, so two plugins cannot claim one type and no plugin can
|
|
28
|
+
* claim one of the core's. The name has a core block's own shape: a
|
|
29
|
+
* lowerCamelCase word of at most 32 characters.
|
|
30
|
+
*/
|
|
31
|
+
export declare const PLUGIN_BLOCK_NAME_PATTERN: RegExp;
|
|
32
|
+
/** The type id a page stores a plugin's block under. */
|
|
33
|
+
export declare function pluginBlockType(pluginId: string, name: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* The pictures the page editor can show beside a plugin's block.
|
|
36
|
+
*
|
|
37
|
+
* A name rather than an image, as for the core's blocks: the editor draws each
|
|
38
|
+
* one in the theme's own colours, and a manifest carries no markup. `plugin` is
|
|
39
|
+
* the one to choose when none of the others says what the block is.
|
|
40
|
+
*/
|
|
41
|
+
export declare const PLUGIN_BLOCK_ICONS: readonly ["plugin", "paragraph", "heading", "image", "form", "news", "calendar", "documents", "people", "facts", "contact", "questions"];
|
|
42
|
+
export type PluginBlockIcon = (typeof PLUGIN_BLOCK_ICONS)[number];
|
|
43
|
+
/**
|
|
44
|
+
* Where the page editor files a plugin's block.
|
|
45
|
+
*
|
|
46
|
+
* The core's categories, less `layout`: a layout block arranges other blocks,
|
|
47
|
+
* and a plugin's block holds none.
|
|
48
|
+
*/
|
|
49
|
+
export declare const PLUGIN_BLOCK_CATEGORIES: readonly ["text", "media", "association"];
|
|
50
|
+
export type PluginBlockCategory = (typeof PLUGIN_BLOCK_CATEGORIES)[number];
|
|
51
|
+
/**
|
|
52
|
+
* One block a plugin declares, as the manifest carries it.
|
|
53
|
+
*
|
|
54
|
+
* `labelKey` is an i18n key in the plugin's own namespace, like every other
|
|
55
|
+
* label a manifest names. The settings are the same declaration the plugin's
|
|
56
|
+
* own settings form is made of, and the page editor renders them as a form on
|
|
57
|
+
* the block: one set of values per block on a page, validated by the host on
|
|
58
|
+
* every save.
|
|
59
|
+
*/
|
|
60
|
+
export declare const pluginBlockSchema: z.ZodObject<{
|
|
61
|
+
name: z.ZodString;
|
|
62
|
+
labelKey: z.ZodString;
|
|
63
|
+
icon: z.ZodDefault<z.ZodEnum<{
|
|
64
|
+
calendar: "calendar";
|
|
65
|
+
contact: "contact";
|
|
66
|
+
documents: "documents";
|
|
67
|
+
facts: "facts";
|
|
68
|
+
form: "form";
|
|
69
|
+
heading: "heading";
|
|
70
|
+
image: "image";
|
|
71
|
+
news: "news";
|
|
72
|
+
paragraph: "paragraph";
|
|
73
|
+
people: "people";
|
|
74
|
+
plugin: "plugin";
|
|
75
|
+
questions: "questions";
|
|
76
|
+
}>>;
|
|
77
|
+
category: z.ZodDefault<z.ZodEnum<{
|
|
78
|
+
association: "association";
|
|
79
|
+
media: "media";
|
|
80
|
+
text: "text";
|
|
81
|
+
}>>;
|
|
82
|
+
settingsSchema: z.ZodDefault<z.ZodObject<{
|
|
83
|
+
fields: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
84
|
+
key: z.ZodString;
|
|
85
|
+
labelKey: z.ZodString;
|
|
86
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
87
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
88
|
+
type: z.ZodLiteral<"text">;
|
|
89
|
+
default: z.ZodOptional<z.ZodString>;
|
|
90
|
+
minLength: z.ZodOptional<z.ZodInt>;
|
|
91
|
+
maxLength: z.ZodOptional<z.ZodInt>;
|
|
92
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
93
|
+
key: z.ZodString;
|
|
94
|
+
labelKey: z.ZodString;
|
|
95
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
96
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
97
|
+
type: z.ZodLiteral<"number">;
|
|
98
|
+
default: z.ZodOptional<z.ZodNumber>;
|
|
99
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
100
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
101
|
+
integer: z.ZodDefault<z.ZodBoolean>;
|
|
102
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
103
|
+
key: z.ZodString;
|
|
104
|
+
labelKey: z.ZodString;
|
|
105
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
106
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
107
|
+
type: z.ZodLiteral<"boolean">;
|
|
108
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
109
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
110
|
+
key: z.ZodString;
|
|
111
|
+
labelKey: z.ZodString;
|
|
112
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
113
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
114
|
+
type: z.ZodLiteral<"select">;
|
|
115
|
+
default: z.ZodOptional<z.ZodString>;
|
|
116
|
+
options: z.ZodArray<z.ZodObject<{
|
|
117
|
+
value: z.ZodString;
|
|
118
|
+
labelKey: z.ZodString;
|
|
119
|
+
}, z.core.$strip>>;
|
|
120
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
121
|
+
key: z.ZodString;
|
|
122
|
+
labelKey: z.ZodString;
|
|
123
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
124
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
125
|
+
type: z.ZodLiteral<"secret">;
|
|
126
|
+
minLength: z.ZodOptional<z.ZodInt>;
|
|
127
|
+
maxLength: z.ZodOptional<z.ZodInt>;
|
|
128
|
+
}, z.core.$strip>], "type">>;
|
|
129
|
+
}, z.core.$strip>>;
|
|
130
|
+
}, z.core.$strict>;
|
|
131
|
+
export type PluginBlockDeclaration = z.infer<typeof pluginBlockSchema>;
|
|
132
|
+
/**
|
|
133
|
+
* The blocks a manifest declares. At most sixteen, each name once.
|
|
134
|
+
*
|
|
135
|
+
* A name appearing twice would be one type id with two renderers, and a page
|
|
136
|
+
* that holds it would render with whichever registered last.
|
|
137
|
+
*/
|
|
138
|
+
export declare const pluginBlocksSchema: z.ZodArray<z.ZodObject<{
|
|
139
|
+
name: z.ZodString;
|
|
140
|
+
labelKey: z.ZodString;
|
|
141
|
+
icon: z.ZodDefault<z.ZodEnum<{
|
|
142
|
+
calendar: "calendar";
|
|
143
|
+
contact: "contact";
|
|
144
|
+
documents: "documents";
|
|
145
|
+
facts: "facts";
|
|
146
|
+
form: "form";
|
|
147
|
+
heading: "heading";
|
|
148
|
+
image: "image";
|
|
149
|
+
news: "news";
|
|
150
|
+
paragraph: "paragraph";
|
|
151
|
+
people: "people";
|
|
152
|
+
plugin: "plugin";
|
|
153
|
+
questions: "questions";
|
|
154
|
+
}>>;
|
|
155
|
+
category: z.ZodDefault<z.ZodEnum<{
|
|
156
|
+
association: "association";
|
|
157
|
+
media: "media";
|
|
158
|
+
text: "text";
|
|
159
|
+
}>>;
|
|
160
|
+
settingsSchema: z.ZodDefault<z.ZodObject<{
|
|
161
|
+
fields: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
162
|
+
key: z.ZodString;
|
|
163
|
+
labelKey: z.ZodString;
|
|
164
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
165
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
166
|
+
type: z.ZodLiteral<"text">;
|
|
167
|
+
default: z.ZodOptional<z.ZodString>;
|
|
168
|
+
minLength: z.ZodOptional<z.ZodInt>;
|
|
169
|
+
maxLength: z.ZodOptional<z.ZodInt>;
|
|
170
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
171
|
+
key: z.ZodString;
|
|
172
|
+
labelKey: z.ZodString;
|
|
173
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
174
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
175
|
+
type: z.ZodLiteral<"number">;
|
|
176
|
+
default: z.ZodOptional<z.ZodNumber>;
|
|
177
|
+
min: z.ZodOptional<z.ZodNumber>;
|
|
178
|
+
max: z.ZodOptional<z.ZodNumber>;
|
|
179
|
+
integer: z.ZodDefault<z.ZodBoolean>;
|
|
180
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
181
|
+
key: z.ZodString;
|
|
182
|
+
labelKey: z.ZodString;
|
|
183
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
184
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
185
|
+
type: z.ZodLiteral<"boolean">;
|
|
186
|
+
default: z.ZodOptional<z.ZodBoolean>;
|
|
187
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
188
|
+
key: z.ZodString;
|
|
189
|
+
labelKey: z.ZodString;
|
|
190
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
191
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
192
|
+
type: z.ZodLiteral<"select">;
|
|
193
|
+
default: z.ZodOptional<z.ZodString>;
|
|
194
|
+
options: z.ZodArray<z.ZodObject<{
|
|
195
|
+
value: z.ZodString;
|
|
196
|
+
labelKey: z.ZodString;
|
|
197
|
+
}, z.core.$strip>>;
|
|
198
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
199
|
+
key: z.ZodString;
|
|
200
|
+
labelKey: z.ZodString;
|
|
201
|
+
hintKey: z.ZodOptional<z.ZodString>;
|
|
202
|
+
required: z.ZodDefault<z.ZodBoolean>;
|
|
203
|
+
type: z.ZodLiteral<"secret">;
|
|
204
|
+
minLength: z.ZodOptional<z.ZodInt>;
|
|
205
|
+
maxLength: z.ZodOptional<z.ZodInt>;
|
|
206
|
+
}, z.core.$strip>], "type">>;
|
|
207
|
+
}, z.core.$strip>>;
|
|
208
|
+
}, z.core.$strict>>;
|
|
209
|
+
/**
|
|
210
|
+
* The elements a rendered block may contain.
|
|
211
|
+
*
|
|
212
|
+
* Text and its structure, and nothing that loads, runs or styles anything. An
|
|
213
|
+
* element outside this list is left out together with everything inside it,
|
|
214
|
+
* because what an unknown element holds is not text the plugin meant a reader
|
|
215
|
+
* to see: the body of a script, a stylesheet, a template.
|
|
216
|
+
*
|
|
217
|
+
* Headings start at the second level, as a page's own blocks do: the page's
|
|
218
|
+
* title is its first-level heading.
|
|
219
|
+
*/
|
|
220
|
+
export declare const PLUGIN_BLOCK_ELEMENTS: readonly ["p", "h2", "h3", "h4", "ul", "ol", "li", "dl", "dt", "dd", "strong", "em", "small", "code", "blockquote", "a", "br", "span", "div", "section", "table", "caption", "thead", "tbody", "tfoot", "tr", "th", "td", "time"];
|
|
221
|
+
export type PluginBlockElementName = (typeof PLUGIN_BLOCK_ELEMENTS)[number];
|
|
222
|
+
/**
|
|
223
|
+
* The attributes an element may carry, by element. Every other one is left out.
|
|
224
|
+
*
|
|
225
|
+
* href on `a`: http, https, mailto or a path on this instance. Any other
|
|
226
|
+
* address - `javascript:` above all - leaves the link out and keeps
|
|
227
|
+
* its text. A link to another host is given noopener and
|
|
228
|
+
* noreferrer by the host.
|
|
229
|
+
* dateTime on `time`: the machine-readable date beside the one shown.
|
|
230
|
+
* scope on `th`: `row`, `col`, `rowgroup` or `colgroup`.
|
|
231
|
+
*
|
|
232
|
+
* No `class`, no `style` and no `id`: the theme decides how the website looks,
|
|
233
|
+
* and the host wraps every plugin's block in one element the theme can style.
|
|
234
|
+
*/
|
|
235
|
+
export declare const PLUGIN_BLOCK_ATTRIBUTES: Readonly<Partial<Record<PluginBlockElementName, readonly string[]>>>;
|
|
236
|
+
/** One element of a rendered block. */
|
|
237
|
+
export interface PluginBlockElement {
|
|
238
|
+
readonly tag: PluginBlockElementName;
|
|
239
|
+
readonly attributes?: Readonly<Record<string, string>>;
|
|
240
|
+
readonly children?: readonly PluginBlockNode[];
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* A piece of a rendered block: text, or an element.
|
|
244
|
+
*
|
|
245
|
+
* Text is text. It is escaped as it is printed, so `"<b>"` reads as the three
|
|
246
|
+
* characters and is never an element.
|
|
247
|
+
*/
|
|
248
|
+
export type PluginBlockNode = string | PluginBlockElement;
|
|
249
|
+
/** What a render function answers with. Null, or nothing, renders nothing. */
|
|
250
|
+
export type PluginBlockContent = PluginBlockNode | readonly PluginBlockNode[] | null | undefined;
|
|
251
|
+
/**
|
|
252
|
+
* What a block's render function is told.
|
|
253
|
+
*
|
|
254
|
+
* The block's own settings, already validated against its declaration with
|
|
255
|
+
* the declared defaults applied, and the reader's language with a translation
|
|
256
|
+
* function in the plugin's own namespace. Nothing about the reader: the same
|
|
257
|
+
* page is rendered for a visitor with no account and for a member, and what a
|
|
258
|
+
* block may say must not depend on who is reading it.
|
|
259
|
+
*/
|
|
260
|
+
export interface PluginBlockRenderContext {
|
|
261
|
+
/** The block's type id, `<plugin id>/<name>`. */
|
|
262
|
+
readonly type: string;
|
|
263
|
+
readonly settings: PluginSettingsValues;
|
|
264
|
+
/** The language the page is being rendered in: `sv` or `en`. */
|
|
265
|
+
readonly locale: string;
|
|
266
|
+
/** Translates a key from the plugin's own locale files. */
|
|
267
|
+
readonly t: (key: string, values?: Readonly<Record<string, string | number>>) => string;
|
|
268
|
+
/**
|
|
269
|
+
* Aborted when the host stops waiting for this block.
|
|
270
|
+
*
|
|
271
|
+
* A render that has not answered within PLUGIN_BLOCK_RENDER_TIMEOUT_MS is
|
|
272
|
+
* left off the page, and the page is sent without it. The host cannot stop
|
|
273
|
+
* the plugin's code, so a render doing slow work of its own should hand this
|
|
274
|
+
* on to whatever it is waiting for.
|
|
275
|
+
*/
|
|
276
|
+
readonly signal: PluginBlockAbortSignal;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* The `AbortSignal` a render function is given. See {@link PluginAbortSignal}.
|
|
280
|
+
*/
|
|
281
|
+
export type PluginBlockAbortSignal = PluginAbortSignal;
|
|
282
|
+
/**
|
|
283
|
+
* How long the host waits for one block to render, in milliseconds.
|
|
284
|
+
*
|
|
285
|
+
* Every block on a page renders at the same time, so this is also about the
|
|
286
|
+
* longest a plugin can add to a page's answer. A website's front page has to
|
|
287
|
+
* answer quickly for a visitor with no account, and a block that cannot is
|
|
288
|
+
* left off rather than waited for.
|
|
289
|
+
*/
|
|
290
|
+
export declare const PLUGIN_BLOCK_RENDER_TIMEOUT_MS = 2000;
|
|
291
|
+
/** What a plugin hands the host for one block its manifest declared. */
|
|
292
|
+
export interface PluginBlockRegistration {
|
|
293
|
+
/** The block's name as the manifest declares it, not its type id. */
|
|
294
|
+
readonly name: string;
|
|
295
|
+
readonly render: (context: PluginBlockRenderContext) => PluginBlockContent | Promise<PluginBlockContent>;
|
|
296
|
+
}
|
|
297
|
+
export interface PluginBlocks {
|
|
298
|
+
/**
|
|
299
|
+
* Registers the render function of a block the manifest declared.
|
|
300
|
+
*
|
|
301
|
+
* Callable from the module factory onwards, as `host.actions.register` is: a
|
|
302
|
+
* call made before the application exists is kept until it does. A name the
|
|
303
|
+
* manifest does not declare stops the plugin serving and is reported as
|
|
304
|
+
* `block-refused`. A declared block with no render function registered is
|
|
305
|
+
* not offered in the page editor, and a page that already holds one shows
|
|
306
|
+
* nothing in its place.
|
|
307
|
+
*/
|
|
308
|
+
register: (registration: PluginBlockRegistration) => void;
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=blocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"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"}
|
package/dist/blocks.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { pluginSettingsSchema } from "./settings-schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Blocks a plugin adds to the association's website.
|
|
5
|
+
*
|
|
6
|
+
* A page on the website is a list of blocks, never markup (ADR 0006), and a
|
|
7
|
+
* plugin's block is one more type in that list. The manifest declares it - its
|
|
8
|
+
* name, how the page editor offers it and the settings the board fills in - and
|
|
9
|
+
* the server bundle registers the function that renders it. The host does the
|
|
10
|
+
* rest: it offers the block in the editor, validates the settings on every
|
|
11
|
+
* save, calls the render function while it renders the page, and decides what
|
|
12
|
+
* of the answer reaches the visitor's browser.
|
|
13
|
+
*
|
|
14
|
+
* What the render function returns is a small tree of elements rather than a
|
|
15
|
+
* string of HTML. The host reads it against a short list of elements and
|
|
16
|
+
* attributes and prints what passes through the same renderer as the rest of
|
|
17
|
+
* the page, so a script, a stylesheet, an event handler or a picture from
|
|
18
|
+
* another host has no way into the markup however the tree was built. The
|
|
19
|
+
* website's content security policy refuses all four as well; the list is what
|
|
20
|
+
* keeps the page from carrying them at all.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* The name of one block, unique within its plugin.
|
|
24
|
+
*
|
|
25
|
+
* The block's type id is composed by the host as `<plugin id>/<name>`, which is
|
|
26
|
+
* what a page stores, so two plugins cannot claim one type and no plugin can
|
|
27
|
+
* claim one of the core's. The name has a core block's own shape: a
|
|
28
|
+
* lowerCamelCase word of at most 32 characters.
|
|
29
|
+
*/
|
|
30
|
+
export const PLUGIN_BLOCK_NAME_PATTERN = /^[a-z][a-zA-Z0-9]{0,31}$/;
|
|
31
|
+
/** The type id a page stores a plugin's block under. */
|
|
32
|
+
export function pluginBlockType(pluginId, name) {
|
|
33
|
+
return `${pluginId}/${name}`;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The pictures the page editor can show beside a plugin's block.
|
|
37
|
+
*
|
|
38
|
+
* A name rather than an image, as for the core's blocks: the editor draws each
|
|
39
|
+
* one in the theme's own colours, and a manifest carries no markup. `plugin` is
|
|
40
|
+
* the one to choose when none of the others says what the block is.
|
|
41
|
+
*/
|
|
42
|
+
export const PLUGIN_BLOCK_ICONS = [
|
|
43
|
+
"plugin",
|
|
44
|
+
"paragraph",
|
|
45
|
+
"heading",
|
|
46
|
+
"image",
|
|
47
|
+
"form",
|
|
48
|
+
"news",
|
|
49
|
+
"calendar",
|
|
50
|
+
"documents",
|
|
51
|
+
"people",
|
|
52
|
+
"facts",
|
|
53
|
+
"contact",
|
|
54
|
+
"questions",
|
|
55
|
+
];
|
|
56
|
+
/**
|
|
57
|
+
* Where the page editor files a plugin's block.
|
|
58
|
+
*
|
|
59
|
+
* The core's categories, less `layout`: a layout block arranges other blocks,
|
|
60
|
+
* and a plugin's block holds none.
|
|
61
|
+
*/
|
|
62
|
+
export const PLUGIN_BLOCK_CATEGORIES = [
|
|
63
|
+
"text",
|
|
64
|
+
"media",
|
|
65
|
+
"association",
|
|
66
|
+
];
|
|
67
|
+
/**
|
|
68
|
+
* One block a plugin declares, as the manifest carries it.
|
|
69
|
+
*
|
|
70
|
+
* `labelKey` is an i18n key in the plugin's own namespace, like every other
|
|
71
|
+
* label a manifest names. The settings are the same declaration the plugin's
|
|
72
|
+
* own settings form is made of, and the page editor renders them as a form on
|
|
73
|
+
* the block: one set of values per block on a page, validated by the host on
|
|
74
|
+
* every save.
|
|
75
|
+
*/
|
|
76
|
+
export const pluginBlockSchema = z.strictObject({
|
|
77
|
+
name: z
|
|
78
|
+
.string()
|
|
79
|
+
.regex(PLUGIN_BLOCK_NAME_PATTERN, "must be a lowerCamelCase word of at most 32 characters"),
|
|
80
|
+
labelKey: z.string().min(1).max(200),
|
|
81
|
+
icon: z.enum(PLUGIN_BLOCK_ICONS).default("plugin"),
|
|
82
|
+
category: z.enum(PLUGIN_BLOCK_CATEGORIES).default("association"),
|
|
83
|
+
/*
|
|
84
|
+
* No secret field. A block's values are stored in the page that holds it
|
|
85
|
+
* and are read by whoever renders the page, so a credential there would be
|
|
86
|
+
* published with it.
|
|
87
|
+
*/
|
|
88
|
+
settingsSchema: pluginSettingsSchema
|
|
89
|
+
.refine((schema) => schema.fields.every((field) => field.type !== "secret"), {
|
|
90
|
+
message: "a block's settings may not declare a secret field: they are published with the page",
|
|
91
|
+
})
|
|
92
|
+
.default({ fields: [] }),
|
|
93
|
+
});
|
|
94
|
+
/**
|
|
95
|
+
* The blocks a manifest declares. At most sixteen, each name once.
|
|
96
|
+
*
|
|
97
|
+
* A name appearing twice would be one type id with two renderers, and a page
|
|
98
|
+
* that holds it would render with whichever registered last.
|
|
99
|
+
*/
|
|
100
|
+
export const pluginBlocksSchema = z
|
|
101
|
+
.array(pluginBlockSchema)
|
|
102
|
+
.max(16)
|
|
103
|
+
.superRefine((blocks, ctx) => {
|
|
104
|
+
const seen = new Set();
|
|
105
|
+
for (const [index, block] of blocks.entries()) {
|
|
106
|
+
if (seen.has(block.name)) {
|
|
107
|
+
ctx.addIssue({
|
|
108
|
+
code: "custom",
|
|
109
|
+
path: [index, "name"],
|
|
110
|
+
message: `two blocks are declared with the name "${block.name}"`,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
seen.add(block.name);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
/**
|
|
117
|
+
* The elements a rendered block may contain.
|
|
118
|
+
*
|
|
119
|
+
* Text and its structure, and nothing that loads, runs or styles anything. An
|
|
120
|
+
* element outside this list is left out together with everything inside it,
|
|
121
|
+
* because what an unknown element holds is not text the plugin meant a reader
|
|
122
|
+
* to see: the body of a script, a stylesheet, a template.
|
|
123
|
+
*
|
|
124
|
+
* Headings start at the second level, as a page's own blocks do: the page's
|
|
125
|
+
* title is its first-level heading.
|
|
126
|
+
*/
|
|
127
|
+
export const PLUGIN_BLOCK_ELEMENTS = [
|
|
128
|
+
"p",
|
|
129
|
+
"h2",
|
|
130
|
+
"h3",
|
|
131
|
+
"h4",
|
|
132
|
+
"ul",
|
|
133
|
+
"ol",
|
|
134
|
+
"li",
|
|
135
|
+
"dl",
|
|
136
|
+
"dt",
|
|
137
|
+
"dd",
|
|
138
|
+
"strong",
|
|
139
|
+
"em",
|
|
140
|
+
"small",
|
|
141
|
+
"code",
|
|
142
|
+
"blockquote",
|
|
143
|
+
"a",
|
|
144
|
+
"br",
|
|
145
|
+
"span",
|
|
146
|
+
"div",
|
|
147
|
+
"section",
|
|
148
|
+
"table",
|
|
149
|
+
"caption",
|
|
150
|
+
"thead",
|
|
151
|
+
"tbody",
|
|
152
|
+
"tfoot",
|
|
153
|
+
"tr",
|
|
154
|
+
"th",
|
|
155
|
+
"td",
|
|
156
|
+
"time",
|
|
157
|
+
];
|
|
158
|
+
/**
|
|
159
|
+
* The attributes an element may carry, by element. Every other one is left out.
|
|
160
|
+
*
|
|
161
|
+
* href on `a`: http, https, mailto or a path on this instance. Any other
|
|
162
|
+
* address - `javascript:` above all - leaves the link out and keeps
|
|
163
|
+
* its text. A link to another host is given noopener and
|
|
164
|
+
* noreferrer by the host.
|
|
165
|
+
* dateTime on `time`: the machine-readable date beside the one shown.
|
|
166
|
+
* scope on `th`: `row`, `col`, `rowgroup` or `colgroup`.
|
|
167
|
+
*
|
|
168
|
+
* No `class`, no `style` and no `id`: the theme decides how the website looks,
|
|
169
|
+
* and the host wraps every plugin's block in one element the theme can style.
|
|
170
|
+
*/
|
|
171
|
+
export const PLUGIN_BLOCK_ATTRIBUTES = {
|
|
172
|
+
a: ["href"],
|
|
173
|
+
time: ["dateTime"],
|
|
174
|
+
th: ["scope"],
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* How long the host waits for one block to render, in milliseconds.
|
|
178
|
+
*
|
|
179
|
+
* Every block on a page renders at the same time, so this is also about the
|
|
180
|
+
* longest a plugin can add to a page's answer. A website's front page has to
|
|
181
|
+
* answer quickly for a visitor with no account, and a block that cannot is
|
|
182
|
+
* left off rather than waited for.
|
|
183
|
+
*/
|
|
184
|
+
export const PLUGIN_BLOCK_RENDER_TIMEOUT_MS = 2000;
|
|
185
|
+
//# sourceMappingURL=blocks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blocks.js","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"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"}
|