@blogmcp/community 0.1.0 → 0.3.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 +162 -13
- package/dist/blogmcp-community.global.js +8 -8
- package/dist/chunks/mount--2_V2q3M.js +10063 -0
- package/dist/core/attrs.d.ts +42 -1
- package/dist/core/badge.d.ts +30 -0
- package/dist/core/centre.d.ts +28 -0
- package/dist/core/digest-token.d.ts +2 -0
- package/dist/core/discussion.d.ts +120 -15
- package/dist/core/follow.d.ts +26 -0
- package/dist/core/format.d.ts +7 -0
- package/dist/core/forum-category.d.ts +85 -0
- package/dist/core/forum-search.d.ts +35 -0
- package/dist/core/forum-state.d.ts +30 -0
- package/dist/core/forum-words.d.ts +8 -0
- package/dist/core/forum.d.ts +21 -0
- package/dist/core/moderation.d.ts +80 -0
- package/dist/core/onboarding.d.ts +49 -2
- package/dist/core/outcomes.d.ts +2 -1
- package/dist/core/panel.d.ts +17 -1
- package/dist/core/profile.d.ts +45 -0
- package/dist/core/push.d.ts +63 -0
- package/dist/core/realtime.d.ts +46 -0
- package/dist/core/settings.d.ts +53 -0
- package/dist/core/text.d.ts +13 -0
- package/dist/core/topic.d.ts +47 -0
- package/dist/element.d.ts +47 -1
- package/dist/global.d.ts +8 -4
- package/dist/index.d.ts +20 -3
- package/dist/index.js +62 -12
- package/dist/mount.d.ts +89 -0
- package/dist/react.d.ts +27 -3
- package/dist/react.js +48 -4
- package/dist/ui/BadgeView.vue.d.ts +13 -0
- package/dist/ui/DiscussionView.vue.d.ts +11 -0
- package/dist/ui/FollowButtonView.vue.d.ts +17 -0
- package/dist/ui/FollowToggle.vue.d.ts +6 -0
- package/dist/ui/ForumCategoryView.vue.d.ts +13 -0
- package/dist/ui/ForumModerationView.vue.d.ts +12 -0
- package/dist/ui/ForumNotices.vue.d.ts +7 -0
- package/dist/ui/ForumSearchView.vue.d.ts +11 -0
- package/dist/ui/ForumView.vue.d.ts +12 -0
- package/dist/ui/LinkedText.vue.d.ts +1 -0
- package/dist/ui/MemberSettingsView.vue.d.ts +13 -0
- package/dist/ui/MembersOnly.vue.d.ts +15 -0
- package/dist/ui/MessageComposer.vue.d.ts +8 -2
- package/dist/ui/MessageMenu.vue.d.ts +2 -0
- package/dist/ui/ModeratorDialog.vue.d.ts +11 -0
- package/dist/ui/NotificationCentreView.vue.d.ts +12 -0
- package/dist/ui/OnboardingSteps.vue.d.ts +1 -1
- package/dist/ui/ProfileView.vue.d.ts +13 -0
- package/dist/ui/TopicRow.vue.d.ts +10 -0
- package/dist/ui/TopicView.vue.d.ts +32 -0
- package/dist/ui/WelcomeView.vue.d.ts +12 -0
- package/dist/ui/context.d.ts +7 -1
- package/dist/ui/discussion-context.d.ts +11 -3
- package/dist/vue.d.ts +273 -3
- package/dist/vue.js +235 -5
- package/package.json +3 -3
- package/src/core/attrs.ts +61 -2
- package/src/core/badge.ts +120 -0
- package/src/core/centre.ts +136 -0
- package/src/core/digest-token.ts +26 -0
- package/src/core/discussion.ts +497 -46
- package/src/core/follow.ts +139 -0
- package/src/core/format.ts +22 -0
- package/src/core/forum-category.ts +323 -0
- package/src/core/forum-search.ts +153 -0
- package/src/core/forum-state.ts +59 -0
- package/src/core/forum-words.ts +38 -0
- package/src/core/forum.ts +83 -0
- package/src/core/moderation.ts +414 -0
- package/src/core/onboarding.ts +177 -18
- package/src/core/outcomes.ts +23 -1
- package/src/core/panel.ts +39 -4
- package/src/core/profile.ts +155 -0
- package/src/core/push.ts +174 -0
- package/src/core/realtime.ts +52 -0
- package/src/core/settings.ts +363 -0
- package/src/core/text.ts +32 -0
- package/src/core/topic.ts +234 -0
- package/src/element.ts +124 -6
- package/src/global.ts +40 -4
- package/src/index.ts +84 -2
- package/src/mount.ts +250 -1
- package/src/react.ts +90 -3
- package/src/ui/BadgeView.vue +51 -0
- package/src/ui/DiscussionView.vue +43 -3
- package/src/ui/FollowButtonView.vue +85 -0
- package/src/ui/FollowToggle.vue +39 -0
- package/src/ui/ForumCategoryView.vue +243 -0
- package/src/ui/ForumModerationView.vue +309 -0
- package/src/ui/ForumNotices.vue +23 -0
- package/src/ui/ForumSearchView.vue +171 -0
- package/src/ui/ForumView.vue +128 -0
- package/src/ui/LinkedText.vue +11 -5
- package/src/ui/MemberSettingsView.vue +175 -0
- package/src/ui/MembersOnly.vue +59 -0
- package/src/ui/MessageComposer.vue +64 -11
- package/src/ui/MessageItem.vue +36 -7
- package/src/ui/MessageMenu.vue +3 -2
- package/src/ui/ModeratorDialog.vue +102 -0
- package/src/ui/MyCommunityView.vue +12 -0
- package/src/ui/NoticeStatusView.vue +15 -2
- package/src/ui/NotificationCentreView.vue +193 -0
- package/src/ui/OnboardingSteps.vue +17 -6
- package/src/ui/ProfileView.vue +102 -0
- package/src/ui/TopicRow.vue +70 -0
- package/src/ui/TopicView.vue +395 -0
- package/src/ui/WelcomeView.vue +72 -0
- package/src/ui/context.ts +8 -3
- package/src/ui/discussion-context.ts +11 -3
- package/src/ui/styles.css +30 -0
- package/src/vue.ts +271 -3
- package/dist/chunks/mount-DzjwnHyx.js +0 -4597
package/README.md
CHANGED
|
@@ -4,13 +4,68 @@ The community elements for your own site, over `@blogmcp/sdk/community`:
|
|
|
4
4
|
|
|
5
5
|
- `<blogmcp-discussion>`: the discussion under an article. A two-level thread, the composer, reactions,
|
|
6
6
|
reports, blocks, the inline onboarding, and the states of a member's own messages ("awaiting review",
|
|
7
|
-
removed, deleted)
|
|
7
|
+
removed, deleted). Where the tenant asks for the art. 9 consent, the onboarding asks it the way the tenant set
|
|
8
|
+
it in kb-api: one consent, or one per controller the consent text names, and a refusal that still lets the
|
|
9
|
+
member write in public where the tenant allows it. Your site passes nothing for this;
|
|
8
10
|
- `<blogmcp-notice-form>`: the notice form for anyone, signed in or not (DSA art. 16), with Cloudflare
|
|
9
11
|
Turnstile;
|
|
10
12
|
- `<blogmcp-my-community>`: the reader's „Moje komunita" panel. It holds statements of reasons and appeals,
|
|
11
|
-
reports, notifications, the consent,
|
|
13
|
+
reports, notifications, the consent (to withdraw it, or to give one the member refused), the export and the
|
|
14
|
+
profile's deletion. It also renders a statement
|
|
12
15
|
page (`decision-id`) and a notifier's status page (`#t=<receipt>` in the address).
|
|
13
16
|
|
|
17
|
+
With the community module (M2) there are five more:
|
|
18
|
+
|
|
19
|
+
- `<blogmcp-notification-centre>`: the member's notifications, newest first. Older ones load a page at a time,
|
|
20
|
+
„Jen nepřečtené" filters them, each one or all can be marked read, and each row links its subject where your
|
|
21
|
+
site has a page for it (a decision's statement, the settings, „Moje komunita"). It links your settings page;
|
|
22
|
+
- `<blogmcp-badge>`: the unread count for your header, a link to the centre. It asks once who is viewing, then
|
|
23
|
+
the count every 60 s while the tab is visible and again when it is shown again. It renders nothing for a
|
|
24
|
+
visitor, a reader who never joined, a module that is off, or nothing unread;
|
|
25
|
+
- `<blogmcp-member-settings>`: the six notification switches (replies, mentions, topics, browser notifications,
|
|
26
|
+
the daily e-mail digest, the quiet night 22:00–7:00), each saved on its own; this browser's notifications;
|
|
27
|
+
and the digest e-mail's unsubscribe link (below);
|
|
28
|
+
- `<blogmcp-profile handle="…">`: a member's public profile: name, avatar, since when they are a member, the
|
|
29
|
+
bio as text and the trust level as a label („Nový člen", „Člen", „Stálý člen", „Důvěryhodný člen"), never a
|
|
30
|
+
number; with the forum, „Moderátor" and the categories the member moderates now (an appointment, not a trust
|
|
31
|
+
level);
|
|
32
|
+
- `<blogmcp-welcome>`: the page after joining: the rules in summary and three links (the discussions, the
|
|
33
|
+
settings, the member's own profile; a visitor gets your sign-in link instead).
|
|
34
|
+
|
|
35
|
+
With the forum (M3) there are six more. The forum is for members only: a visitor reads one sentence and your
|
|
36
|
+
sign-in link, a member short of the onboarding „Vstoupit do komunity" (the onboarding opens in place; a forum write
|
|
37
|
+
needs the art. 9 consent whatever the tenant asks elsewhere).
|
|
38
|
+
|
|
39
|
+
- `<blogmcp-forum>`: the forum's index. The categories in the team's order, each with its count, its latest
|
|
40
|
+
topics and the link to all of them, and a search box that opens your search page with the query in the
|
|
41
|
+
address's fragment (`#q=…`, never the query string);
|
|
42
|
+
- `<blogmcp-forum-category slug="…">`: a category's topics, by activity or newest, pinned first, more a page at
|
|
43
|
+
a time. Where members open topics, the new-topic composer (a title of at most 200 characters, the opening post,
|
|
44
|
+
the link to the rules); a topic that waits for review says so and lists for its author only. In „Články" the
|
|
45
|
+
rows are the article discussions, each with its follow button;
|
|
46
|
+
- `<blogmcp-topic conversation-id="…">`: a topic's page. The header (title, category, closed, pinned, count),
|
|
47
|
+
the thread in the forum's words („příspěvek", where an article's discussion says „komentář"), the composer,
|
|
48
|
+
reactions, reports, the follow button and, for the opening post's author, the title's edit. A moderator of the
|
|
49
|
+
topic's category gets its menu: close or reopen it, pin it, move it, remove a message (with the rule and the
|
|
50
|
+
facts; the author gets a statement of reasons) or pass a message to the team;
|
|
51
|
+
- `<blogmcp-forum-search>`: the forum's search, as text. It reads the query from `#q=…`; a query shorter than two
|
|
52
|
+
characters is said, never sent;
|
|
53
|
+
- `<blogmcp-follow-button target-kind="…" target-id="…">`: follow a topic or an article discussion
|
|
54
|
+
(`conversation`) or a category (`category`). A follow the member may not have reads „not available"; an unfollow
|
|
55
|
+
never fails;
|
|
56
|
+
- `<blogmcp-forum-moderation>`: a category moderator's queue. The package of each case as text, the decision with
|
|
57
|
+
its statement previewed before it is decided, a matter passed to the team, the messages waiting for review
|
|
58
|
+
published or refused. It renders nothing for a member who moderates nothing.
|
|
59
|
+
|
|
60
|
+
A missing title reads one of three ways: „Smazané téma" only when the opening post was deleted, its own words
|
|
61
|
+
while it is withheld from the viewer, and its title with „Čeká na kontrolu" for the author of a topic waiting for
|
|
62
|
+
review. The forum's own brake pauses the forum's writes only, the article discussions' brake the discussions only
|
|
63
|
+
(the module's brake both); while the team is away the forum says so in one sentence.
|
|
64
|
+
|
|
65
|
+
`<blogmcp-discussion>` also links every `@handle` in a comment to that member's profile page (for a signed-in
|
|
66
|
+
reader; an anonymous one reads the mention as text), and takes live updates through its `realtime` property
|
|
67
|
+
(below).
|
|
68
|
+
|
|
14
69
|
Each element lives in a shadow root and renders text only. A member's links pass through `sanitizeUrl` and
|
|
15
70
|
carry `rel="nofollow ugc noopener noreferrer"`. Every text comes from the SDK's catalogue
|
|
16
71
|
(`communityMessage`), in Czech or English.
|
|
@@ -74,21 +129,27 @@ import { KbDiscussion } from '@blogmcp/community/react' // a client component
|
|
|
74
129
|
<KbDiscussion articleId={article.id} apiBase="/api/community" signInHref="/sign-in" />
|
|
75
130
|
```
|
|
76
131
|
|
|
77
|
-
`KbNoticeForm
|
|
132
|
+
`KbNoticeForm`, `KbMyCommunity`, `KbNotificationCentre`, `KbBadge`, `KbMemberSettings`, `KbProfile`,
|
|
133
|
+
`KbWelcome` and the forum's `KbForum`, `KbForumCategory`, `KbTopic`, `KbForumSearch`, `KbFollowButton` and
|
|
134
|
+
`KbForumModeration` work the same way. Each wrapper mounts its element after hydration and
|
|
78
135
|
removes it on unmount. It renders a single empty `<div data-blogmcp-community="…">` as the mount point: the
|
|
79
136
|
discussion is part of the page's flow, so the element goes where the wrapper is.
|
|
80
137
|
|
|
81
|
-
`mountDiscussion(o)`, `mountNoticeForm(o)
|
|
82
|
-
|
|
138
|
+
`mountDiscussion(o)`, `mountNoticeForm(o)`, `mountMyCommunity(o)`, `mountNotificationCentre(o)`, `mountBadge(o)`,
|
|
139
|
+
`mountMemberSettings(o)`, `mountProfile(o)`, `mountWelcome(o)` and the forum's `mountForum(o)`,
|
|
140
|
+
`mountForumCategory(o)`, `mountTopic(o)`, `mountForumSearch(o)`, `mountFollowButton(o)` and
|
|
141
|
+
`mountForumModeration(o)` do the same from any client-side hook. Each returns the unmount function. The tag names
|
|
142
|
+
are exported too (`DISCUSSION_ELEMENT_TAG` … `FORUM_MODERATION_ELEMENT_TAG`), and `defineForumElement()` and its
|
|
143
|
+
siblings register one element alone.
|
|
83
144
|
|
|
84
145
|
**Plain HTML**
|
|
85
146
|
|
|
86
147
|
```html
|
|
87
148
|
<blogmcp-discussion article-id="…" api-base="/api/community" sign-in-href="/prihlaseni"></blogmcp-discussion>
|
|
88
|
-
<script src="https://cdn.jsdelivr.net/npm/@blogmcp/community@0.
|
|
149
|
+
<script src="https://cdn.jsdelivr.net/npm/@blogmcp/community@0.3.0/dist/blogmcp-community.global.js" nonce="…"></script>
|
|
89
150
|
```
|
|
90
151
|
|
|
91
|
-
The script build (`@blogmcp/community/global`) registers all
|
|
152
|
+
The script build (`@blogmcp/community/global`) registers all fourteen elements. It exposes
|
|
92
153
|
`window.BlogmcpCommunity` and gives the elements its own `nonce`.
|
|
93
154
|
|
|
94
155
|
## Attributes
|
|
@@ -108,10 +169,34 @@ The script build (`@blogmcp/community/global`) registers all three elements. It
|
|
|
108
169
|
| | `turnstile-site-key` | your Turnstile site key; without it no widget renders |
|
|
109
170
|
| `<blogmcp-my-community>` | `decision-id` | open this statement of reasons |
|
|
110
171
|
| | `sign-in-href` | your sign-in page |
|
|
172
|
+
| `<blogmcp-notification-centre>` | `sign-in-href` | your sign-in page (a visitor's link) |
|
|
173
|
+
| `<blogmcp-badge>` | `poll-ms` | how often to read the count while the tab is visible (default 60000, and never less — a smaller value reads as 60000; 0 = once, and when the tab is shown again) |
|
|
174
|
+
| `<blogmcp-member-settings>` | `sw-path` | your service worker route (default `${site-base}/sw.js`) |
|
|
175
|
+
| | `sign-in-href` | your sign-in page |
|
|
176
|
+
| `<blogmcp-profile>` | `handle` | the member's handle (an `@` in front is fine) |
|
|
177
|
+
| | `sign-in-href` | your sign-in page (profiles are for signed-in readers) |
|
|
178
|
+
| `<blogmcp-welcome>` | `sign-in-href` | your sign-in page (in the profile link's place, for a visitor) |
|
|
179
|
+
| `<blogmcp-forum>` | `sign-in-href` | your sign-in page (a visitor's link) |
|
|
180
|
+
| `<blogmcp-forum-category>` | `slug` | the category's slug |
|
|
181
|
+
| | `sign-in-href` | your sign-in page |
|
|
182
|
+
| `<blogmcp-topic>` | `conversation-id` | the topic (its conversation id) |
|
|
183
|
+
| | `sign-in-href` | your sign-in page |
|
|
184
|
+
| | `poll-ms` | how often to check for new posts while the topic is in view (default 20000; 0 = off) |
|
|
185
|
+
| `<blogmcp-forum-search>` | `sign-in-href` | your sign-in page |
|
|
186
|
+
| `<blogmcp-follow-button>` | `target-kind` | `conversation` (a topic, an article discussion) or `category` |
|
|
187
|
+
| | `target-id` | its id |
|
|
188
|
+
| | `following` | `true` / `false` when your page knows it (left out: the element reads the member's follows) |
|
|
189
|
+
| `<blogmcp-forum-moderation>` | `category-id` | one of the moderator's categories only (left out: all of them) |
|
|
111
190
|
|
|
112
191
|
`routes` names your community pages: `statementPath` (with `{id}`), `myCommunityPath`, `rulesPath`,
|
|
113
|
-
`reportPath
|
|
114
|
-
|
|
192
|
+
`reportPath`, `noticesPath` and, with the module, `profilePath` (with `{handle}`), `settingsPath`,
|
|
193
|
+
`notificationsPath`, `welcomePath` and `discussionsPath`, and with the forum `forumPath`, `categoryPath` (with
|
|
194
|
+
`{slug}`), `topicPath` (with `{id}`, the topic's conversation id) and `searchPath`. Each is a full path on your site, used as it is. A page you leave out
|
|
195
|
+
falls back to the managed blog's pages: `${site-base}/community/…`. `articlePath` (with `{slug}`; no default)
|
|
196
|
+
is your article page — the managed blogs' `/blog/articles/{slug}`, a shop's `/blog/{slug}`: the notification
|
|
197
|
+
centre links a reply or a mention to its message there (`…/<slug>#bcm-msg-<seq>`), and without it those rows stay
|
|
198
|
+
text. The discussion gives every message the anchor `bcm-msg-<seq>` and, opened at one, scrolls to it itself once
|
|
199
|
+
its first page is in (the rows live in a shadow root, where the browser's own jump cannot reach). The tenant's own statement and „Moje
|
|
115
200
|
komunita" paths, set in its community settings, come before that fallback.
|
|
116
201
|
`consultationPath` (no default) turns the regulated preset's adverse-event note into a link to your
|
|
117
202
|
consultation page.
|
|
@@ -120,8 +205,67 @@ as soon as it reads it.
|
|
|
120
205
|
|
|
121
206
|
A `transport` property replaces the HTTP layer, for tests.
|
|
122
207
|
|
|
208
|
+
## Live updates (`realtime`)
|
|
209
|
+
|
|
210
|
+
The discussion keeps itself fresh by polling. For live updates, import the SDK's realtime entry yourself and pass
|
|
211
|
+
its `createRealtimeSession` as the discussion's `realtime` property (a property, never an attribute) — or the
|
|
212
|
+
topic's: `<blogmcp-topic>` takes it the same way (a change of the topic's header, its title or state, reads the
|
|
213
|
+
topic again). Your bundle
|
|
214
|
+
then needs `centrifuge` (≥ 5.7), the entry's peer dependency; the elements never import either, so a site
|
|
215
|
+
without it ships no socket code.
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
import { createRealtimeSession } from '@blogmcp/sdk/community/realtime'
|
|
219
|
+
import { KbDiscussion } from '@blogmcp/community/react'
|
|
220
|
+
|
|
221
|
+
<KbDiscussion articleId={article.id} apiBase="/api/community" realtime={createRealtimeSession} />
|
|
222
|
+
// plain: document.querySelector('blogmcp-discussion').realtime = createRealtimeSession
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
The element starts the session over its own discussion after the first page is read, and stops it when it
|
|
226
|
+
unmounts. It starts none for an anonymous reader, nor while the community's live updates are off (the module is
|
|
227
|
+
`read_only` or off, or the instance runs no realtime): the discussion polls then, with no socket. A session that
|
|
228
|
+
falls back to polling — kb-api answers `REALTIME_OFF`, or the server ends the connection for good — makes the
|
|
229
|
+
discussion say once that live updates are off; it is never reopened. When the session was revoked (4501), the
|
|
230
|
+
session asks kb-api for a fresh token once first: a member whose own password change ended the old session keeps
|
|
231
|
+
the page live under the new one; a refusal, or a second 4501, falls back for good. While the socket cannot get
|
|
232
|
+
through (the subscription is not live 15 s after connecting, or after the connection dropped), the discussion polls
|
|
233
|
+
meanwhile and says so once; Centrifuge keeps reconnecting, and the sentence goes when it is live again. An article
|
|
234
|
+
without comments yet has no channel to subscribe to: it polls for the first one and is never called off for that.
|
|
235
|
+
|
|
236
|
+
The composer knows the member's mention limit (`me/get`'s `caps.mentionsPerMessage`, by trust level): a comment
|
|
237
|
+
that mentions more distinct `@handle`s says so as it is typed and is not sent (kb-api refuses it too).
|
|
238
|
+
|
|
239
|
+
The URL to connect to comes from kb-api's token answer (the instance's own host, `/rt/…`), never from your
|
|
240
|
+
configuration.
|
|
241
|
+
|
|
242
|
+
## Browser notifications and the digest's unsubscribe link
|
|
243
|
+
|
|
244
|
+
`<blogmcp-member-settings>` shows this browser's notifications only while the community offers them. „Zapnout
|
|
245
|
+
upozornění" (the member's click; nothing is registered on page load) registers **your** service worker at
|
|
246
|
+
`sw-path`, asks the member's permission, subscribes the browser and hands the subscription to kb-api; „Vypnout"
|
|
247
|
+
ends it. Serve the worker from `@blogmcp/sdk/community/sw` (`communityServiceWorkerSource`, as
|
|
248
|
+
`COMMUNITY_SW_CONTENT_TYPE`, `Cache-Control: no-cache`) at that route, and the manifest from
|
|
249
|
+
`@blogmcp/sdk/community/manifest`. Inside Facebook's or Instagram's app the element offers „Otevřít v prohlížeči"
|
|
250
|
+
with the page's URL instead; on an iPhone or iPad it explains that the site must be added to the home screen first.
|
|
251
|
+
After a key rotation (or kb-api's „switch it on again" notice) it asks the member to switch them on again. The
|
|
252
|
+
switch reads on only for a subscription this member made in this browser (a shared browser shows another member's
|
|
253
|
+
as off) and that kb-api still holds: with the permission granted, the element asks kb-api on load whether it still
|
|
254
|
+
holds this browser's endpoint (`me/push/status` — a read: no worker registered, no permission asked, nothing
|
|
255
|
+
subscribed). kb-api drops a subscription after a sign-out everywhere or a dead endpoint without telling the page;
|
|
256
|
+
the switch then reads off and stays off until the member presses „Zapnout upozornění" — a sign-out everywhere never
|
|
257
|
+
brings notifications back on its own. When kb-api cannot answer (the status, or the current key's `me/push/vapid` that is checked first), the switch
|
|
258
|
+
reads off too, without a sentence. The element also clears `#u=` from the address when
|
|
259
|
+
it is misconfigured and renders nothing.
|
|
260
|
+
|
|
261
|
+
The digest e-mail links to your settings page with the unsubscribe token in the fragment (`#u=…`). The element
|
|
262
|
+
reads it once, clears it from the address bar, and sends it only when the member clicks „Odhlásit denní souhrn"
|
|
263
|
+
(a mail scanner that opens the link unsubscribes nobody). That works without a session. Route your settings page
|
|
264
|
+
(`settingsPath`) where kb-api's e-mails point.
|
|
265
|
+
|
|
123
266
|
Events (bubbling, composed):
|
|
124
|
-
- `bcm-posted`, `{ state: 'visible' | 'held' }`: the reader's comment went out;
|
|
267
|
+
- `bcm-posted`, `{ state: 'visible' | 'held' }`: the reader's comment (or, in a topic, post) went out;
|
|
268
|
+
- `bcm-topic-created`, `{ conversationId, state: 'visible' | 'held' }`: the member opened a topic;
|
|
125
269
|
- `bcm-notice-submitted`, `{ contactKept }`: a notice was received.
|
|
126
270
|
|
|
127
271
|
## Look
|
|
@@ -134,7 +278,9 @@ The properties are `--bcm-bg`, `-fg`, `-muted`, `-line`, `-soft`, `-accent`, `-a
|
|
|
134
278
|
## Content Security Policy
|
|
135
279
|
|
|
136
280
|
- The styles are one `<style>` in each shadow root, carrying the nonce you pass.
|
|
137
|
-
- `connect-src 'self'` is enough: the elements only talk to your own base.
|
|
281
|
+
- `connect-src 'self'` is enough: the elements only talk to your own base. With live updates on a headless
|
|
282
|
+
site, add your instance's host (`https://<instance host>` and `wss://<instance host>`): the socket goes there.
|
|
283
|
+
- Browser notifications need `worker-src 'self'` (and `manifest-src 'self'` for the manifest).
|
|
138
284
|
- The notice form with Turnstile needs `script-src` and `frame-src` for `https://challenges.cloudflare.com`.
|
|
139
285
|
Only a page with the notice form loads that script.
|
|
140
286
|
|
|
@@ -142,6 +288,9 @@ The properties are `--bcm-bg`, `-fg`, `-muted`, `-line`, `-soft`, `-accent`, `-a
|
|
|
142
288
|
|
|
143
289
|
```bash
|
|
144
290
|
npm run build # ESM + the <script> build (+ size budget, 200 KiB gzip)
|
|
145
|
-
npm test # vitest (happy-dom): controllers, store, onboarding, outcomes, elements, text-only and closed-path scans
|
|
146
|
-
npm run test:e2e # Playwright: desktop + iPhone profile + a plain bundler, mocked community API (ports 8286/8287)
|
|
291
|
+
npm test # vitest (happy-dom): controllers, store, onboarding, outcomes, elements, the forum's six, text-only and closed-path scans
|
|
292
|
+
npm run test:e2e # Playwright: desktop + iPhone profile + a plain bundler, mocked community API (ports 8286/8287);
|
|
293
|
+
# m2.e2e.ts drives the centre (its link to a reply's message), the badge, the settings,
|
|
294
|
+
# a profile, the welcome page and the composer's mention limit; plain-bundler.e2e.ts mounts
|
|
295
|
+
# M1's, M2's and the forum's elements from dist/ (a topic opened from a category included)
|
|
147
296
|
```
|