@solutiondesk/help 0.0.0-stage → 1.0.0-1a5deb7
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 +21 -0
- package/README.md +298 -2
- package/dist/fumadocs.d.ts +780 -0
- package/dist/fumadocs.js +981 -0
- package/dist/index.cjs +344 -0
- package/dist/index.d.cts +479 -0
- package/dist/index.d.ts +479 -0
- package/dist/index.js +334 -0
- package/package.json +84 -3
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
import { JSXElementConstructor, ReactNode, ComponentType } from 'react';
|
|
2
|
+
import { MetaData, PageData, StaticSource, VirtualFile, DynamicSource } from 'fumadocs-core/source';
|
|
3
|
+
import { TOCItemType } from 'fumadocs-core/toc';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The answers of the public help center API (`GET /v1/help/{workspace}/{site}/…`).
|
|
7
|
+
* Written by hand so the package has no dependencies; a drift test in the
|
|
8
|
+
* SolutionDesk repository keeps them identical to the API's own contracts.
|
|
9
|
+
*
|
|
10
|
+
* Only what is publicly visible ever appears here: a page that is published,
|
|
11
|
+
* public and placed in the site's navigation — except the one page a valid
|
|
12
|
+
* preview token names. Absent values are `null`, never a missing key.
|
|
13
|
+
*
|
|
14
|
+
* Paths: a page's path is its folder slugs plus its slug, without leading or
|
|
15
|
+
* trailing slash (`guides/login`) — a `group` folder adds no slug; the site's
|
|
16
|
+
* home page has the path `""`.
|
|
17
|
+
*/
|
|
18
|
+
/** The doc site itself. */
|
|
19
|
+
interface HelpPublicSite {
|
|
20
|
+
/** The site's handle in the URL (`hilfe`). */
|
|
21
|
+
slug: string;
|
|
22
|
+
name: string;
|
|
23
|
+
/** Main language (BCP 47 code, e.g. `de`). */
|
|
24
|
+
language: string;
|
|
25
|
+
/** Every language the site is offered in, main language first. */
|
|
26
|
+
languages: string[];
|
|
27
|
+
/** The docs website's base address (`https://help.acme.com/docs`), if set. */
|
|
28
|
+
websiteUrl: string | null;
|
|
29
|
+
/** The site's own building blocks pages may use (empty when it defines none). */
|
|
30
|
+
blocks: HelpPublicBlockDefinition[];
|
|
31
|
+
}
|
|
32
|
+
/** What a field of a site's own block holds (see {@link HelpPublicBlockField}). */
|
|
33
|
+
type HelpPublicBlockFieldType = "text" | "longText" | "icon" | "url" | "choice" | "image" | "video" | "boolean";
|
|
34
|
+
/**
|
|
35
|
+
* One field of a site's own block: an attribute of its directive
|
|
36
|
+
* (`key="value"`). `boolean` fields are on when written bare (`key`) or as
|
|
37
|
+
* `key="true"`; every other value is a string. `options` lists a `choice`
|
|
38
|
+
* field's values (null for other types).
|
|
39
|
+
*/
|
|
40
|
+
interface HelpPublicBlockField {
|
|
41
|
+
key: string;
|
|
42
|
+
label: string;
|
|
43
|
+
type: HelpPublicBlockFieldType;
|
|
44
|
+
required: boolean;
|
|
45
|
+
options: string[] | null;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* A building block the site defines itself — WHAT it is; how it looks is the
|
|
49
|
+
* website's own component. Written in Markdown as `:name[label]{…}` in running
|
|
50
|
+
* text (`inline`), `::name[label]{…}` alone on a line (`block`) or
|
|
51
|
+
* `:::name{…}` … `:::` around Markdown content (`container`). `text` is the
|
|
52
|
+
* template of its text version (`{key}` = a field's value, a `boolean` field's
|
|
53
|
+
* label when on; `{{`/`}}` = a brace) — what to show without a component.
|
|
54
|
+
*/
|
|
55
|
+
interface HelpPublicBlockDefinition {
|
|
56
|
+
/** The directive name (`app-button`). */
|
|
57
|
+
name: string;
|
|
58
|
+
/** Display name. */
|
|
59
|
+
label: string;
|
|
60
|
+
kind: "inline" | "block" | "container";
|
|
61
|
+
fields: HelpPublicBlockField[];
|
|
62
|
+
text: string;
|
|
63
|
+
}
|
|
64
|
+
/** A page in the navigation. */
|
|
65
|
+
interface HelpPublicTreePage {
|
|
66
|
+
type: "page";
|
|
67
|
+
/** The page's own slug (the last path segment; `index` for the home page). */
|
|
68
|
+
slug: string;
|
|
69
|
+
path: string;
|
|
70
|
+
title: string;
|
|
71
|
+
description: string | null;
|
|
72
|
+
/** A Lucide icon name (`BookOpen`). */
|
|
73
|
+
icon: string | null;
|
|
74
|
+
}
|
|
75
|
+
/** A folder (Fumadocs: a directory with `meta.json`). Empty folders are left out. */
|
|
76
|
+
interface HelpPublicTreeFolder {
|
|
77
|
+
type: "folder";
|
|
78
|
+
/** Stable node id. */
|
|
79
|
+
id: string;
|
|
80
|
+
slug: string;
|
|
81
|
+
/** The folder's path (its index page, if any, lives here; a group's is its parent's). */
|
|
82
|
+
path: string;
|
|
83
|
+
title: string;
|
|
84
|
+
/** A short line under a tab's name in the tab menu (Fumadocs `description`); null without one. */
|
|
85
|
+
description: string | null;
|
|
86
|
+
icon: string | null;
|
|
87
|
+
/** A tab (top level only; Fumadocs `root`). */
|
|
88
|
+
root: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Adds no segment to its pages' paths (Fumadocs `(name)` folder): `path` is
|
|
91
|
+
* the parent's, a top-level group's index page is the home (`""`).
|
|
92
|
+
*/
|
|
93
|
+
group: boolean;
|
|
94
|
+
defaultOpen: boolean;
|
|
95
|
+
collapsible: boolean;
|
|
96
|
+
/** The folder's own page, shown at the folder's path; null without one. */
|
|
97
|
+
index: HelpPublicTreePage | null;
|
|
98
|
+
/**
|
|
99
|
+
* List `index` as the folder's first entry (after a section title it starts
|
|
100
|
+
* with); the folder's name then only opens it (Fumadocs: `index` in `pages`).
|
|
101
|
+
*/
|
|
102
|
+
listIndex: boolean;
|
|
103
|
+
children: HelpPublicTreeNode[];
|
|
104
|
+
}
|
|
105
|
+
/** A labelled divider between entries (Fumadocs `---Title---`). */
|
|
106
|
+
interface HelpPublicTreeSeparator {
|
|
107
|
+
type: "separator";
|
|
108
|
+
id: string;
|
|
109
|
+
title: string | null;
|
|
110
|
+
icon: string | null;
|
|
111
|
+
}
|
|
112
|
+
/** A menu entry pointing elsewhere: an https address or a path on the docs website. */
|
|
113
|
+
interface HelpPublicTreeLink {
|
|
114
|
+
type: "link";
|
|
115
|
+
id: string;
|
|
116
|
+
title: string;
|
|
117
|
+
url: string;
|
|
118
|
+
icon: string | null;
|
|
119
|
+
/** Open as an external link (Fumadocs `external:`). */
|
|
120
|
+
external: boolean;
|
|
121
|
+
}
|
|
122
|
+
/** One entry of the navigation tree, discriminated by `type`. */
|
|
123
|
+
type HelpPublicTreeNode = HelpPublicTreePage | HelpPublicTreeFolder | HelpPublicTreeSeparator | HelpPublicTreeLink;
|
|
124
|
+
/** `GET site?lang=` — the site and its navigation in one language. */
|
|
125
|
+
interface HelpPublicSitePayload {
|
|
126
|
+
site: HelpPublicSite;
|
|
127
|
+
/** The language the labels are in (`?lang=`: exact, base language, else the main one). */
|
|
128
|
+
locale: string;
|
|
129
|
+
/** The site's languages, main first (same as `site.languages`). */
|
|
130
|
+
languages: string[];
|
|
131
|
+
tree: HelpPublicTreeNode[];
|
|
132
|
+
}
|
|
133
|
+
/** A visible page without its text (`GET pages`: builds and sitemaps). */
|
|
134
|
+
interface HelpPublicPageSummary {
|
|
135
|
+
path: string;
|
|
136
|
+
slug: string;
|
|
137
|
+
title: string;
|
|
138
|
+
description: string | null;
|
|
139
|
+
icon: string | null;
|
|
140
|
+
/** The language this page's texts are in (falls back to the main language per page). */
|
|
141
|
+
locale: string;
|
|
142
|
+
/** The languages this page is offered in, main language first. */
|
|
143
|
+
languages: string[];
|
|
144
|
+
/** When it was first published (ISO 8601). */
|
|
145
|
+
publishedAt: string | null;
|
|
146
|
+
/** "Updated on", set deliberately by the authors; null when never set. */
|
|
147
|
+
contentUpdatedAt: string | null;
|
|
148
|
+
/** The last change of any kind (ISO 8601) — for sitemaps and caches. */
|
|
149
|
+
updatedAt: string;
|
|
150
|
+
/** The page on the docs website (`websiteUrl` + path), null without a website address. */
|
|
151
|
+
url: string | null;
|
|
152
|
+
}
|
|
153
|
+
/** `GET pages?lang=` — every visible page in reading order. */
|
|
154
|
+
interface HelpPublicPagesPayload {
|
|
155
|
+
locale: string;
|
|
156
|
+
languages: string[];
|
|
157
|
+
pages: HelpPublicPageSummary[];
|
|
158
|
+
}
|
|
159
|
+
/** A heading of the page, with the anchor id the `html` gives it. */
|
|
160
|
+
interface HelpPublicHeading {
|
|
161
|
+
level: number;
|
|
162
|
+
text: string;
|
|
163
|
+
id: string;
|
|
164
|
+
}
|
|
165
|
+
/** The directives a page uses (a website loads tab scripts only when needed). */
|
|
166
|
+
type HelpPublicBlock = "callout" | "steps" | "step" | "tabs" | "tab" | "cards" | "card";
|
|
167
|
+
/** A folder above a page, outermost first; `path` only when the folder has its own page. */
|
|
168
|
+
interface HelpPublicBreadcrumb {
|
|
169
|
+
title: string;
|
|
170
|
+
path: string | null;
|
|
171
|
+
}
|
|
172
|
+
/** The page before or after, in the tree's reading order (never across tabs). */
|
|
173
|
+
interface HelpPublicPageLink {
|
|
174
|
+
path: string;
|
|
175
|
+
title: string;
|
|
176
|
+
}
|
|
177
|
+
/** One page with its text. */
|
|
178
|
+
interface HelpPublicPage extends HelpPublicPageSummary {
|
|
179
|
+
/**
|
|
180
|
+
* The page's Markdown with directives (`:::callout`, `::::steps`, …, and the
|
|
181
|
+
* site's own blocks as written — see `site.blocks`).
|
|
182
|
+
*/
|
|
183
|
+
markdown: string;
|
|
184
|
+
/** Safe server-rendered HTML of `markdown` (stable `sd-*` classes for the directives). */
|
|
185
|
+
html: string;
|
|
186
|
+
headings: HelpPublicHeading[];
|
|
187
|
+
blocks: HelpPublicBlock[];
|
|
188
|
+
/** The site's own building blocks the page uses, by name (in the site's order). */
|
|
189
|
+
customBlocks: string[];
|
|
190
|
+
breadcrumbs: HelpPublicBreadcrumb[];
|
|
191
|
+
previous: HelpPublicPageLink | null;
|
|
192
|
+
next: HelpPublicPageLink | null;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* `GET page?path=&lang=`. A path the page had before answers `301` with
|
|
196
|
+
* `Location` pointing at the new `page?path=` and the body {@link HelpPublicRedirect}.
|
|
197
|
+
*/
|
|
198
|
+
interface HelpPublicPagePayload {
|
|
199
|
+
page: HelpPublicPage;
|
|
200
|
+
}
|
|
201
|
+
/** The body of a `301` for a moved page. */
|
|
202
|
+
interface HelpPublicRedirect {
|
|
203
|
+
/** The page's current path. */
|
|
204
|
+
redirectTo: string;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* A page as its preview shows it: any status, any visibility, translations as
|
|
208
|
+
* soon as they have a title. `path` is null while the page isn't placed in the
|
|
209
|
+
* navigation (then without breadcrumbs and neighbours).
|
|
210
|
+
*/
|
|
211
|
+
interface HelpPublicPreviewPage extends Omit<HelpPublicPage, "path"> {
|
|
212
|
+
path: string | null;
|
|
213
|
+
status: "draft" | "published" | "archived";
|
|
214
|
+
visibility: "public" | "internal";
|
|
215
|
+
}
|
|
216
|
+
/** `GET preview?token=&lang=` — never cached. */
|
|
217
|
+
interface HelpPublicPreviewPayload {
|
|
218
|
+
page: HelpPublicPreviewPage;
|
|
219
|
+
}
|
|
220
|
+
/** One search hit. Title hits rank above heading hits above text hits. */
|
|
221
|
+
interface HelpPublicSearchHit {
|
|
222
|
+
path: string;
|
|
223
|
+
title: string;
|
|
224
|
+
description: string | null;
|
|
225
|
+
/** Plain text around the first match (escape it before putting it into HTML). */
|
|
226
|
+
excerpt: string;
|
|
227
|
+
/** The best matching heading, for a `path#id` link. */
|
|
228
|
+
heading: {
|
|
229
|
+
id: string;
|
|
230
|
+
text: string;
|
|
231
|
+
} | null;
|
|
232
|
+
/** The page on the docs website, null without a website address. */
|
|
233
|
+
url: string | null;
|
|
234
|
+
}
|
|
235
|
+
/** `GET search?q=&lang=&limit=` — at most 20 hits, best first. */
|
|
236
|
+
interface HelpPublicSearchPayload {
|
|
237
|
+
query: string;
|
|
238
|
+
locale: string;
|
|
239
|
+
languages: string[];
|
|
240
|
+
hits: HelpPublicSearchHit[];
|
|
241
|
+
}
|
|
242
|
+
/** What a help webhook announces. */
|
|
243
|
+
type HelpWebhookEvent = "page.published" | "page.updated" | "page.unpublished" | "page.deleted" | "navigation.updated" | "ping";
|
|
244
|
+
/** The body of a help webhook call (verify it first — see `verifyHelpWebhook`). */
|
|
245
|
+
interface HelpWebhookBody {
|
|
246
|
+
event: HelpWebhookEvent;
|
|
247
|
+
/** The workspace slug, as in the public API path. */
|
|
248
|
+
workspace: string;
|
|
249
|
+
/** The doc site's slug, as in the public API path. */
|
|
250
|
+
site: string;
|
|
251
|
+
/** The page's path (null for `navigation.updated` and `ping`). */
|
|
252
|
+
path: string | null;
|
|
253
|
+
/** Earlier paths — their pages are stale too (for `navigation.updated`: every path that moved). */
|
|
254
|
+
previousPaths: string[];
|
|
255
|
+
/** The languages the page is offered in after the change (the site's for navigation). */
|
|
256
|
+
locales: string[];
|
|
257
|
+
occurredAt: string;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/**
|
|
261
|
+
* Parsing the help center's Markdown the way the API renders it
|
|
262
|
+
* (`packages/db/src/help-markdown.ts`): GFM plus container directives in the
|
|
263
|
+
* generic syntax of `remark-directive`. Only the directive names below mean
|
|
264
|
+
* something, plus the site's own blocks (`blocks.ts`); every other directive
|
|
265
|
+
* is printed back as the text it was written as.
|
|
266
|
+
*/
|
|
267
|
+
/** The directive names the help center knows. */
|
|
268
|
+
declare const HELP_BLOCKS: readonly ["callout", "steps", "step", "tabs", "tab", "cards", "card"];
|
|
269
|
+
type HelpBlockName = (typeof HELP_BLOCKS)[number];
|
|
270
|
+
/** `callout` types (anything else is shown as `info`). */
|
|
271
|
+
declare const HELP_CALLOUT_TYPES: readonly ["info", "warn", "error", "success", "idea"];
|
|
272
|
+
type HelpCalloutType = (typeof HELP_CALLOUT_TYPES)[number];
|
|
273
|
+
/**
|
|
274
|
+
* The link target if it is one a reader may follow (http(s), mailto, `/path`,
|
|
275
|
+
* `#anchor`), else null. The same rule as the API's `safeMarkdownHref`:
|
|
276
|
+
*
|
|
277
|
+
* 1. Surrounding whitespace is trimmed.
|
|
278
|
+
* 2. Any ASCII control character anywhere → unsafe.
|
|
279
|
+
* 3. A target starting with `//`, `/\`, `\/` or `\\` (protocol-relative) → unsafe.
|
|
280
|
+
* 4. Otherwise allowed: `http://…` / `https://…`, `mailto:…`, `/…` and `#…`,
|
|
281
|
+
* each without whitespace inside.
|
|
282
|
+
*/
|
|
283
|
+
declare function safeHelpHref(raw: string | null | undefined): string | null;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* A doc site's own building blocks (`site.blocks`) in the page Markdown — the
|
|
287
|
+
* same rules as the API (`packages/db/src/help-blocks.ts`, `help-markdown.ts`,
|
|
288
|
+
* contract in `docs/help/06-eigene-bausteine.md`), copied so the package has no
|
|
289
|
+
* dependency on the API's code; `test/blocks.test.tsx` holds both in step.
|
|
290
|
+
*
|
|
291
|
+
* The Markdown parser (micromark's directive extension) finds the directives;
|
|
292
|
+
* a use only counts when its name is defined, it is written in its kind's form
|
|
293
|
+
* (`:name` inline, `::name` alone on a line, `:::name` around content) and its
|
|
294
|
+
* source re-reads under the API's stricter syntax (label and attributes on one
|
|
295
|
+
* line, the basic character references) — otherwise it stays literal text.
|
|
296
|
+
*/
|
|
297
|
+
/** A field's checked value: `boolean` fields are true/false, every other type a string. */
|
|
298
|
+
type HelpBlockValue = string | boolean;
|
|
299
|
+
/** A block's checked field values, in the definition's field order. */
|
|
300
|
+
type HelpBlockValues = Record<string, HelpBlockValue>;
|
|
301
|
+
/**
|
|
302
|
+
* A block's attributes as checked field values, by the API's rules: only
|
|
303
|
+
* defined fields; an absent `boolean` is `false`; an empty value counts as
|
|
304
|
+
* absent; invalid values (a `javascript:` link, a malformed icon, a choice
|
|
305
|
+
* not offered) and attributes without a field are left out.
|
|
306
|
+
*/
|
|
307
|
+
declare function helpBlockValues(block: Pick<HelpPublicBlockDefinition, "fields">, attributes: Readonly<Record<string, string>>): HelpBlockValues;
|
|
308
|
+
/**
|
|
309
|
+
* A block's text version: its template with every `{key}` replaced by the
|
|
310
|
+
* field's value (a `boolean` by its label when on, else nothing; a missing
|
|
311
|
+
* value by nothing), `{{`/`}}` as braces, then `label` after a space;
|
|
312
|
+
* whitespace collapsed. What `HelpBody` shows without a component, and what
|
|
313
|
+
* search and the outline read.
|
|
314
|
+
*/
|
|
315
|
+
declare function helpBlockText(block: Pick<HelpPublicBlockDefinition, "fields" | "text">, values: Readonly<HelpBlockValues>, label?: string): string;
|
|
316
|
+
|
|
317
|
+
interface HelpCalloutProps {
|
|
318
|
+
/** `info`, `warn`, `error`, `success` or `idea` (an unknown type arrives as `info`). */
|
|
319
|
+
type: HelpCalloutType;
|
|
320
|
+
title?: string;
|
|
321
|
+
children: ReactNode;
|
|
322
|
+
}
|
|
323
|
+
interface HelpStepsProps {
|
|
324
|
+
children: ReactNode;
|
|
325
|
+
}
|
|
326
|
+
interface HelpStepProps {
|
|
327
|
+
title?: string;
|
|
328
|
+
/** The title's anchor id (a step's title is a heading of the page, level 3). */
|
|
329
|
+
id?: string;
|
|
330
|
+
children: ReactNode;
|
|
331
|
+
}
|
|
332
|
+
interface HelpTabsProps {
|
|
333
|
+
/** The tab titles, in order (unique). */
|
|
334
|
+
items: string[];
|
|
335
|
+
children: ReactNode;
|
|
336
|
+
}
|
|
337
|
+
interface HelpTabProps {
|
|
338
|
+
/** The tab's entry in `items`. */
|
|
339
|
+
value: string;
|
|
340
|
+
children: ReactNode;
|
|
341
|
+
}
|
|
342
|
+
interface HelpCardsProps {
|
|
343
|
+
children: ReactNode;
|
|
344
|
+
}
|
|
345
|
+
interface HelpCardProps {
|
|
346
|
+
title: string;
|
|
347
|
+
/** A safe link target (http(s), mailto, `/path`, `#anchor`), else absent. */
|
|
348
|
+
href?: string;
|
|
349
|
+
/** The rendered icon (see `HelpBodyProps.icon`). */
|
|
350
|
+
icon?: ReactNode;
|
|
351
|
+
children: ReactNode;
|
|
352
|
+
}
|
|
353
|
+
interface HelpCodeProps {
|
|
354
|
+
code: string;
|
|
355
|
+
/** The fence's language (`ts`), if any. */
|
|
356
|
+
lang?: string;
|
|
357
|
+
/** `title="…"` of the fence, if any. */
|
|
358
|
+
title?: string;
|
|
359
|
+
}
|
|
360
|
+
interface HelpHeadingProps {
|
|
361
|
+
level: 1 | 2 | 3 | 4 | 5 | 6;
|
|
362
|
+
/** The anchor id (the same the API's `headings` name). */
|
|
363
|
+
id: string;
|
|
364
|
+
children: ReactNode;
|
|
365
|
+
}
|
|
366
|
+
interface HelpLinkProps {
|
|
367
|
+
/** Already checked: http(s), mailto, `/path` or `#anchor`. */
|
|
368
|
+
href: string;
|
|
369
|
+
title?: string;
|
|
370
|
+
children: ReactNode;
|
|
371
|
+
}
|
|
372
|
+
interface HelpImageProps {
|
|
373
|
+
src: string;
|
|
374
|
+
alt: string;
|
|
375
|
+
title?: string;
|
|
376
|
+
}
|
|
377
|
+
/** A field value of a site's own block, as its component receives it. */
|
|
378
|
+
type HelpBlockFieldValue = string | boolean | undefined;
|
|
379
|
+
/**
|
|
380
|
+
* The props of a component for one of the site's own blocks
|
|
381
|
+
* (`docs/help/06`). `Fields` names the block's fields: a `boolean` field is
|
|
382
|
+
* always there (`true`/`false`); any other field is a string, or absent when
|
|
383
|
+
* the page leaves it out or its value isn't valid (a `javascript:` link, an
|
|
384
|
+
* icon name that isn't one, a choice not offered) — even a required one, so
|
|
385
|
+
* every field is optional here.
|
|
386
|
+
*
|
|
387
|
+
* @example
|
|
388
|
+
* type AppButtonProps = HelpBlockProps<{ icon: string; label: string }>;
|
|
389
|
+
* function AppButton({ icon, label, children, lang }: AppButtonProps) { … }
|
|
390
|
+
*/
|
|
391
|
+
type HelpBlockProps<Fields extends {
|
|
392
|
+
[K in keyof Fields]: HelpBlockFieldValue;
|
|
393
|
+
} = Record<never, never>> = {
|
|
394
|
+
[K in Exclude<keyof Fields, "block" | "lang" | "children">]?: Fields[K];
|
|
395
|
+
} & {
|
|
396
|
+
/** The block's name (`app-button`). */
|
|
397
|
+
block: string;
|
|
398
|
+
/** The page's language (`page.locale`, or `HelpBody`'s `lang`). */
|
|
399
|
+
lang: string;
|
|
400
|
+
/**
|
|
401
|
+
* `inline`/`block`: the `[label]` (rendered Markdown), if written;
|
|
402
|
+
* `container`: the rendered content — built-in and own blocks included.
|
|
403
|
+
*/
|
|
404
|
+
children?: ReactNode;
|
|
405
|
+
};
|
|
406
|
+
/**
|
|
407
|
+
* A component for a site's own block. Typed loosely so any component fits;
|
|
408
|
+
* type yours with {@link HelpBlockProps}.
|
|
409
|
+
*/
|
|
410
|
+
type HelpBlockComponent = JSXElementConstructor<never>;
|
|
411
|
+
/** Everything `HelpBody` renders through a component — replace any of them. */
|
|
412
|
+
interface HelpBodyComponents {
|
|
413
|
+
Callout: ComponentType<HelpCalloutProps>;
|
|
414
|
+
Steps: ComponentType<HelpStepsProps>;
|
|
415
|
+
Step: ComponentType<HelpStepProps>;
|
|
416
|
+
Tabs: ComponentType<HelpTabsProps>;
|
|
417
|
+
Tab: ComponentType<HelpTabProps>;
|
|
418
|
+
Cards: ComponentType<HelpCardsProps>;
|
|
419
|
+
Card: ComponentType<HelpCardProps>;
|
|
420
|
+
/** A code fence — e.g. swap in Fumadocs' `DynamicCodeBlock` for syntax highlighting. */
|
|
421
|
+
Code: ComponentType<HelpCodeProps>;
|
|
422
|
+
Heading: ComponentType<HelpHeadingProps>;
|
|
423
|
+
Link: ComponentType<HelpLinkProps>;
|
|
424
|
+
Image: ComponentType<HelpImageProps>;
|
|
425
|
+
}
|
|
426
|
+
/** The Fumadocs UI defaults. */
|
|
427
|
+
declare const helpBodyComponents: HelpBodyComponents;
|
|
428
|
+
/**
|
|
429
|
+
* `HelpBody`'s components: any of the built-in ones by their (capitalised)
|
|
430
|
+
* name, and a component per site block by the block's name (`app-button`).
|
|
431
|
+
*/
|
|
432
|
+
interface HelpBodyComponentMap extends Partial<HelpBodyComponents> {
|
|
433
|
+
[block: string]: HelpBlockComponent | undefined;
|
|
434
|
+
}
|
|
435
|
+
interface HelpBodyProps {
|
|
436
|
+
/**
|
|
437
|
+
* The page from the API (`page.data.load()`, `help.page()`, `help.preview()`):
|
|
438
|
+
* its `markdown`, `headings` and `locale` (passed to block components as
|
|
439
|
+
* `lang`). Or pass `markdown` (and `headings`, `lang`) yourself.
|
|
440
|
+
*/
|
|
441
|
+
page?: {
|
|
442
|
+
markdown: string;
|
|
443
|
+
headings?: readonly HelpPublicHeading[];
|
|
444
|
+
locale?: string;
|
|
445
|
+
};
|
|
446
|
+
/** The page's Markdown with directives (`page.markdown` from the API); wins over `page`. */
|
|
447
|
+
markdown?: string;
|
|
448
|
+
/**
|
|
449
|
+
* The page's `headings` from the API: their ids become the headings' anchors,
|
|
450
|
+
* so they always match `getHelpToc(page.headings)`. Without them the ids are
|
|
451
|
+
* computed the API's way.
|
|
452
|
+
*/
|
|
453
|
+
headings?: readonly HelpPublicHeading[];
|
|
454
|
+
/** The page's language for block components (default `page.locale`, else `""`). */
|
|
455
|
+
lang?: string;
|
|
456
|
+
/**
|
|
457
|
+
* The site's own blocks (`page.data.blocks` of a help source, or
|
|
458
|
+
* `site.blocks` from `help.site()`). Without them every such directive stays
|
|
459
|
+
* the text it was written as.
|
|
460
|
+
*/
|
|
461
|
+
blocks?: readonly HelpPublicBlockDefinition[];
|
|
462
|
+
/**
|
|
463
|
+
* Replace any of the default Fumadocs UI components (`Callout`, `Code`, …),
|
|
464
|
+
* and render the site's own blocks with your components, keyed by the
|
|
465
|
+
* block's name: `{ "app-button": AppButton }`. A defined block without a
|
|
466
|
+
* component shows its text version.
|
|
467
|
+
*/
|
|
468
|
+
components?: HelpBodyComponentMap;
|
|
469
|
+
/**
|
|
470
|
+
* Turn a card's Lucide icon name (`Rocket`) into an element, e.g. with
|
|
471
|
+
* `lucide-react`: `(name) => { const Icon = icons[name as keyof typeof icons]; return Icon ? <Icon /> : null; }`.
|
|
472
|
+
* Without it cards show no icon.
|
|
473
|
+
*/
|
|
474
|
+
icon?: (name: string) => ReactNode;
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* A help page's Markdown with its blocks (callout, steps, tabs, cards, titled
|
|
478
|
+
* code fences) as Fumadocs UI components — a React Server Component, also fine
|
|
479
|
+
* on the client. The site's own blocks (`blocks`) render with your
|
|
480
|
+
* `components`, or as their text version. The API's safety rules apply: raw
|
|
481
|
+
* HTML is shown as text, links only to http(s), mailto, `/paths` and
|
|
482
|
+
* `#anchors`, images only from http(s) or `/paths`; unknown directives stay
|
|
483
|
+
* the text they were written as.
|
|
484
|
+
*
|
|
485
|
+
* @example
|
|
486
|
+
* const entry = source.getPage(slugs);
|
|
487
|
+
* const page = await entry.data.load();
|
|
488
|
+
* <DocsBody>
|
|
489
|
+
* <HelpBody page={page} blocks={entry.data.blocks} components={{ "app-button": AppButton }} />
|
|
490
|
+
* </DocsBody>
|
|
491
|
+
*/
|
|
492
|
+
declare function HelpBody(props: HelpBodyProps): ReactNode;
|
|
493
|
+
|
|
494
|
+
/** Per-call options. */
|
|
495
|
+
interface RequestOptions {
|
|
496
|
+
/** Cancels the request (an `AbortSignal`). */
|
|
497
|
+
signal?: unknown;
|
|
498
|
+
/** Extra headers for this request. */
|
|
499
|
+
headers?: Record<string, string>;
|
|
500
|
+
/**
|
|
501
|
+
* Extra `fetch` options for this request, passed through unchanged — e.g.
|
|
502
|
+
* Next.js `{ next: { revalidate: 60, tags: ["legal"] } }` or `{ cache: "no-store" }`.
|
|
503
|
+
*/
|
|
504
|
+
fetchOptions?: Record<string, unknown>;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
interface VerifyWebhookOptions {
|
|
508
|
+
/** How old (or how far in the future) the signed time may be. Default 300 (5 minutes). */
|
|
509
|
+
toleranceSeconds?: number;
|
|
510
|
+
/** "Now" in milliseconds (or a `Date`) — for tests. Default `Date.now()`. */
|
|
511
|
+
now?: number | Date;
|
|
512
|
+
/**
|
|
513
|
+
* A Web Crypto implementation. Default `globalThis.crypto`. On Node 18 pass
|
|
514
|
+
* `require("node:crypto").webcrypto` (Node 19+ has it globally).
|
|
515
|
+
*/
|
|
516
|
+
crypto?: {
|
|
517
|
+
subtle: object;
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
interface HelpRevalidateOptions {
|
|
522
|
+
/** The webhook's signing secret (`whsec_…`), shown once in SolutionDesk. */
|
|
523
|
+
secret: string;
|
|
524
|
+
/**
|
|
525
|
+
* Called with every verified change (not for `ping`, the test call) —
|
|
526
|
+
* e.g. `revalidateTag("solutiondesk-help")` in Next.js. Throwing answers
|
|
527
|
+
* `500`, so SolutionDesk retries the call.
|
|
528
|
+
*/
|
|
529
|
+
revalidate: (body: HelpWebhookBody) => unknown;
|
|
530
|
+
/** Also call `revalidate` for `ping` (default false). */
|
|
531
|
+
includePing?: boolean;
|
|
532
|
+
/** For tests: the signature check's options (clock, Web Crypto). */
|
|
533
|
+
verifyOptions?: VerifyWebhookOptions;
|
|
534
|
+
}
|
|
535
|
+
/** The request parts the handler reads — what every `Request` has. */
|
|
536
|
+
interface HelpWebhookRequest {
|
|
537
|
+
headers: {
|
|
538
|
+
get(name: string): string | null;
|
|
539
|
+
};
|
|
540
|
+
text(): Promise<string>;
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* A webhook endpoint for any framework with `Request`/`Response` (Next.js
|
|
544
|
+
* route handlers, Remix, Astro, Hono, Bun, Deno …): checks the
|
|
545
|
+
* `X-SolutionDesk-Signature`, then calls `revalidate`. Answers `204` when
|
|
546
|
+
* done, `401` for a wrong, missing or expired signature, `400` for a signed
|
|
547
|
+
* body that isn't a help webhook, `500` while no secret is set.
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* // app/api/solutiondesk/help/route.ts
|
|
551
|
+
* import { revalidateTag } from "next/cache";
|
|
552
|
+
* export const POST = createHelpRevalidateHandler({
|
|
553
|
+
* secret: process.env.SOLUTIONDESK_HELP_WEBHOOK_SECRET!,
|
|
554
|
+
* revalidate: () => revalidateTag("solutiondesk-help", "max"),
|
|
555
|
+
* });
|
|
556
|
+
*/
|
|
557
|
+
declare function createHelpRevalidateHandler(options: HelpRevalidateOptions): (request: HelpWebhookRequest) => Promise<Response>;
|
|
558
|
+
|
|
559
|
+
interface LangParams {
|
|
560
|
+
/** The language to ask for; overrides the client's `lang`. */
|
|
561
|
+
lang?: string;
|
|
562
|
+
}
|
|
563
|
+
interface GetPageParams extends LangParams {
|
|
564
|
+
/**
|
|
565
|
+
* What to do when the path is an earlier address of a page (the API answers
|
|
566
|
+
* `301` with `{ redirectTo }`):
|
|
567
|
+
* - `"follow"` (default): return the page; `movedFrom` holds the path you asked for.
|
|
568
|
+
* - `"manual"`: return `{ redirectTo }` with the current path instead.
|
|
569
|
+
*/
|
|
570
|
+
redirect?: "follow" | "manual";
|
|
571
|
+
}
|
|
572
|
+
interface SearchParams extends LangParams {
|
|
573
|
+
/** At most this many hits, 1–20 (default 20). */
|
|
574
|
+
limit?: number;
|
|
575
|
+
}
|
|
576
|
+
/** A page fetched with `redirect: "follow"`. */
|
|
577
|
+
interface HelpPageResult extends HelpPublicPagePayload {
|
|
578
|
+
/**
|
|
579
|
+
* The path you asked for when the page has moved to `page.path` since
|
|
580
|
+
* (redirect your page there, e.g. with a 301); null when it hasn't.
|
|
581
|
+
*/
|
|
582
|
+
movedFrom: string | null;
|
|
583
|
+
}
|
|
584
|
+
interface HelpClient {
|
|
585
|
+
/** The workspace this client reads. */
|
|
586
|
+
readonly workspace: string;
|
|
587
|
+
/** The doc site this client reads (its slug). */
|
|
588
|
+
readonly siteSlug: string;
|
|
589
|
+
/** The site and its navigation tree in one language (`GET …/site`). */
|
|
590
|
+
site(params?: LangParams, options?: RequestOptions): Promise<HelpPublicSitePayload>;
|
|
591
|
+
/** Every visible page without its text, in reading order (`GET …/pages`) — builds and sitemaps. */
|
|
592
|
+
pages(params?: LangParams, options?: RequestOptions): Promise<HelpPublicPagesPayload>;
|
|
593
|
+
/**
|
|
594
|
+
* One visible page with its Markdown, HTML, headings, breadcrumbs and
|
|
595
|
+
* neighbours (`GET …/page?path=`). The home page has the path `""`.
|
|
596
|
+
* Throws a `SolutionDeskError` with status 404 for an unknown or hidden page.
|
|
597
|
+
*/
|
|
598
|
+
page(path: string, params?: GetPageParams & {
|
|
599
|
+
redirect?: "follow";
|
|
600
|
+
}, options?: RequestOptions): Promise<HelpPageResult>;
|
|
601
|
+
page(path: string, params: GetPageParams & {
|
|
602
|
+
redirect: "manual";
|
|
603
|
+
}, options?: RequestOptions): Promise<HelpPublicPagePayload | HelpPublicRedirect>;
|
|
604
|
+
/** One visible page as plain Markdown (`GET …/page.md?path=`), title and source on top. */
|
|
605
|
+
pageMarkdown(path: string, params?: LangParams, options?: RequestOptions): Promise<string>;
|
|
606
|
+
/** Search the visible pages (`GET …/search?q=`): title hits before heading hits before text hits. */
|
|
607
|
+
search(query: string, params?: SearchParams, options?: RequestOptions): Promise<HelpPublicSearchPayload>;
|
|
608
|
+
/**
|
|
609
|
+
* The current state of a page (also a draft or an internal page) for your
|
|
610
|
+
* preview route — the `token` from your preview address (valid for one hour).
|
|
611
|
+
* The API sends it with `Cache-Control: no-store`; in Next.js also pass
|
|
612
|
+
* `fetchOptions: { cache: "no-store" }`.
|
|
613
|
+
*/
|
|
614
|
+
preview(token: string, params?: LangParams, options?: RequestOptions): Promise<HelpPublicPreviewPayload>;
|
|
615
|
+
/** The site's index in the llms.txt format (`GET …/llms.txt`). */
|
|
616
|
+
llmsTxt(params?: LangParams, options?: RequestOptions): Promise<string>;
|
|
617
|
+
/** Every visible page as Markdown, one after the other (`GET …/llms-full.txt`). */
|
|
618
|
+
llmsFullTxt(params?: LangParams, options?: RequestOptions): Promise<string>;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/** Fumadocs' search data of a page (the shape of `remark-structure`). */
|
|
622
|
+
interface HelpStructuredData {
|
|
623
|
+
headings: {
|
|
624
|
+
id: string;
|
|
625
|
+
content: string;
|
|
626
|
+
}[];
|
|
627
|
+
contents: {
|
|
628
|
+
heading: string | undefined;
|
|
629
|
+
content: string;
|
|
630
|
+
}[];
|
|
631
|
+
}
|
|
632
|
+
/**
|
|
633
|
+
* A page's search data for Fumadocs (`createFromSource`): every heading with
|
|
634
|
+
* its anchor, and every paragraph, quote and table cell under the heading it
|
|
635
|
+
* belongs to — code is left out, as in Fumadocs' own `remark-structure`. The
|
|
636
|
+
* site's own `blocks` count as their text version (like the API's search): a
|
|
637
|
+
* container's text version is an entry of its own, followed by its content.
|
|
638
|
+
*/
|
|
639
|
+
declare function helpStructuredData(markdown: string, headings?: readonly HelpPublicHeading[], blocks?: readonly HelpPublicBlockDefinition[]): HelpStructuredData;
|
|
640
|
+
|
|
641
|
+
/** What every page of a help source carries in `page.data`. */
|
|
642
|
+
interface HelpPageData extends PageData {
|
|
643
|
+
title: string;
|
|
644
|
+
description?: string;
|
|
645
|
+
/** A Lucide icon name (`BookOpen`) — add `lucideIconsPlugin()` to `loader()` to render it. */
|
|
646
|
+
icon?: string;
|
|
647
|
+
/** The page's path in the help center (`guides/login`, `""` for the home page). */
|
|
648
|
+
path: string;
|
|
649
|
+
/** The language this file was built for (the `lang` asked for; the API falls back per page). */
|
|
650
|
+
lang: string;
|
|
651
|
+
/**
|
|
652
|
+
* The site's own building blocks (`site.blocks`) — pass them to `HelpBody`
|
|
653
|
+
* (`blocks={page.data.blocks}`) so pages render them with your components.
|
|
654
|
+
*/
|
|
655
|
+
blocks: HelpPublicBlockDefinition[];
|
|
656
|
+
/**
|
|
657
|
+
* The page with its text (`markdown`, `html`, `headings`, `breadcrumbs`,
|
|
658
|
+
* `previous`/`next`). Fetched when called — or right away with
|
|
659
|
+
* `pages: "eager"`, then it resolves to the prefetched page.
|
|
660
|
+
* `null` when the page is gone (taken offline since the source was built,
|
|
661
|
+
* the API answers 404) — render your framework's 404, e.g. `notFound()`.
|
|
662
|
+
*/
|
|
663
|
+
load: () => Promise<HelpPublicPage | null>;
|
|
664
|
+
/**
|
|
665
|
+
* Fumadocs search (`createFromSource`) reads this; built from the page's
|
|
666
|
+
* Markdown. Empty for a page that is gone, so one missing page doesn't
|
|
667
|
+
* break the search index.
|
|
668
|
+
*/
|
|
669
|
+
structuredData: () => Promise<HelpStructuredData>;
|
|
670
|
+
/** The page with its text — only with `pages: "eager"`. */
|
|
671
|
+
page?: HelpPublicPage;
|
|
672
|
+
}
|
|
673
|
+
/** What every folder's `meta.json` of a help source carries. */
|
|
674
|
+
interface HelpMetaData extends MetaData {
|
|
675
|
+
title?: string;
|
|
676
|
+
/** Shown under a tab's name in Fumadocs' tab menu. */
|
|
677
|
+
description?: string;
|
|
678
|
+
icon?: string;
|
|
679
|
+
root?: boolean;
|
|
680
|
+
defaultOpen?: boolean;
|
|
681
|
+
collapsible?: boolean;
|
|
682
|
+
pages: string[];
|
|
683
|
+
pagesIndex?: string;
|
|
684
|
+
}
|
|
685
|
+
type HelpSourceConfig = {
|
|
686
|
+
pageData: HelpPageData;
|
|
687
|
+
metaData: HelpMetaData;
|
|
688
|
+
};
|
|
689
|
+
type HelpSource = StaticSource<HelpSourceConfig>;
|
|
690
|
+
type HelpVirtualFile = VirtualFile<HelpSourceConfig>;
|
|
691
|
+
interface HelpSourceOptions {
|
|
692
|
+
/**
|
|
693
|
+
* Build one set of files per language, for a `loader()` with `i18n` (the
|
|
694
|
+
* default `dot` parser: `guides/login.en.mdx`, `guides/meta.en.json`). Use
|
|
695
|
+
* exactly the `languages` of your `defineI18n()` config. Without it the
|
|
696
|
+
* source holds one language — the client's `lang`, else the site's main
|
|
697
|
+
* language — and file names carry no language.
|
|
698
|
+
*/
|
|
699
|
+
languages?: readonly string[];
|
|
700
|
+
/**
|
|
701
|
+
* `"lazy"` (default): only the navigation is fetched (one request per
|
|
702
|
+
* language); a page's text is fetched when `page.data.load()` is called —
|
|
703
|
+
* cheap to build, one request per rendered page (cache it with your
|
|
704
|
+
* framework's fetch cache, see `requestOptions`).
|
|
705
|
+
* `"eager"`: every page is fetched while building (bounded by `concurrency`)
|
|
706
|
+
* and kept in `page.data.page` — slower to build, nothing fetched later;
|
|
707
|
+
* best for fully static exports.
|
|
708
|
+
*/
|
|
709
|
+
pages?: "lazy" | "eager";
|
|
710
|
+
/** With `pages: "eager"`: at most this many page requests at once (default 6). */
|
|
711
|
+
concurrency?: number;
|
|
712
|
+
/**
|
|
713
|
+
* Passed to every request, e.g. Next.js
|
|
714
|
+
* `{ fetchOptions: { next: { tags: ["solutiondesk-help"], revalidate: 300 } } }`.
|
|
715
|
+
*/
|
|
716
|
+
requestOptions?: RequestOptions;
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* The entry of a tree node in its folder's `meta.json` `pages` (Fumadocs
|
|
720
|
+
* syntax): a page or folder name, `---[Icon]Title---`, `[Icon][Title](url)`,
|
|
721
|
+
* `external:[Title](url)`.
|
|
722
|
+
*/
|
|
723
|
+
declare function helpMetaEntry(node: HelpPublicTreeNode): string;
|
|
724
|
+
interface HelpFilesOptions {
|
|
725
|
+
/** Append `.<lang>` to every file name (Fumadocs' `dot` i18n parser). */
|
|
726
|
+
suffix?: string;
|
|
727
|
+
/** The language the files are for (`page.data.lang`). */
|
|
728
|
+
lang: string;
|
|
729
|
+
/** Loads a page's text (`page.data.load`); `null` when the page is gone. */
|
|
730
|
+
load: (path: string) => Promise<HelpPublicPage | null>;
|
|
731
|
+
/** Prefetched pages by path (`pages: "eager"`); `null` for a page that was gone. */
|
|
732
|
+
prefetched?: ReadonlyMap<string, HelpPublicPage | null>;
|
|
733
|
+
}
|
|
734
|
+
/**
|
|
735
|
+
* The Fumadocs virtual files for one language of the site: a `.mdx` page file
|
|
736
|
+
* per page (a folder's own page as `<folder>/index.mdx`, the home page as
|
|
737
|
+
* `index.mdx` at the top or in a top-level group, any other page named `index`
|
|
738
|
+
* as `index_.mdx`) and a `meta.json` per folder plus one at the top that fixes
|
|
739
|
+
* the order. A group folder is a `(slug)/` directory, so Fumadocs gives its
|
|
740
|
+
* pages the same addresses as the tree (no segment for the group). Every file
|
|
741
|
+
* path is unique. Exported for custom setups; `createHelpSource` uses it.
|
|
742
|
+
*/
|
|
743
|
+
declare function helpTreeToFiles(payload: HelpPublicSitePayload, options: HelpFilesOptions): HelpVirtualFile[];
|
|
744
|
+
/** Every page path of a tree (index pages included), in reading order. */
|
|
745
|
+
declare function helpTreePaths(tree: readonly HelpPublicTreeNode[]): string[];
|
|
746
|
+
/**
|
|
747
|
+
* A Fumadocs source of a help site, for `loader()`:
|
|
748
|
+
*
|
|
749
|
+
* ```ts
|
|
750
|
+
* const help = createHelpClient({ workspace: "acme", site: "docs" });
|
|
751
|
+
* export const source = loader({ baseUrl: "/docs", source: await createHelpSource(help) });
|
|
752
|
+
* ```
|
|
753
|
+
*
|
|
754
|
+
* One `site` request per language builds the navigation; texts come with
|
|
755
|
+
* `page.data.load()` (or all at once with `pages: "eager"`). The tree is a
|
|
756
|
+
* snapshot — rebuild the loader to pick up changes (see the README).
|
|
757
|
+
*/
|
|
758
|
+
declare function createHelpSource(client: HelpClient, options?: HelpSourceOptions): Promise<HelpSource>;
|
|
759
|
+
/**
|
|
760
|
+
* The same as a Fumadocs dynamic source, for `dynamicLoader()` from
|
|
761
|
+
* `fumadocs-core/source/dynamic`: built on first use, rebuilt after
|
|
762
|
+
* `loader.revalidate()` (e.g. from your webhook route).
|
|
763
|
+
*/
|
|
764
|
+
declare function helpDynamicSource(client: HelpClient, options?: HelpSourceOptions): DynamicSource<HelpSourceConfig>;
|
|
765
|
+
|
|
766
|
+
interface HelpTocOptions {
|
|
767
|
+
/** Leave out headings below this level (default 1 — all). */
|
|
768
|
+
minLevel?: number;
|
|
769
|
+
/** Leave out headings above this level (default 6 — all). */
|
|
770
|
+
maxLevel?: number;
|
|
771
|
+
}
|
|
772
|
+
/**
|
|
773
|
+
* The page's table of contents for Fumadocs (`<DocsPage toc={…}>`), from the
|
|
774
|
+
* API's `headings` — the same ids `HelpBody` gives the headings.
|
|
775
|
+
*/
|
|
776
|
+
declare function getHelpToc(headings: readonly HelpPublicHeading[] | {
|
|
777
|
+
headings: readonly HelpPublicHeading[];
|
|
778
|
+
}, options?: HelpTocOptions): TOCItemType[];
|
|
779
|
+
|
|
780
|
+
export { HELP_BLOCKS, HELP_CALLOUT_TYPES, type HelpBlockComponent, type HelpBlockFieldValue, type HelpBlockName, type HelpBlockProps, type HelpBlockValue, type HelpBlockValues, HelpBody, type HelpBodyComponentMap, type HelpBodyComponents, type HelpBodyProps, type HelpCalloutProps, type HelpCalloutType, type HelpCardProps, type HelpCardsProps, type HelpCodeProps, type HelpFilesOptions, type HelpHeadingProps, type HelpImageProps, type HelpLinkProps, type HelpMetaData, type HelpPageData, type HelpRevalidateOptions, type HelpSource, type HelpSourceConfig, type HelpSourceOptions, type HelpStepProps, type HelpStepsProps, type HelpStructuredData, type HelpTabProps, type HelpTabsProps, type HelpTocOptions, type HelpVirtualFile, type HelpWebhookRequest, createHelpRevalidateHandler, createHelpSource, getHelpToc, helpBlockText, helpBlockValues, helpBodyComponents, helpDynamicSource, helpMetaEntry, helpStructuredData, helpTreePaths, helpTreeToFiles, safeHelpHref };
|