@docubook/flame 2.0.0-alpha.2 → 2.0.0-beta.1
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/.docu/components/ScrollTo.tsx +17 -11
- package/.docu/components/Toc.tsx +32 -7
- package/.docu/lib/build.deno.js +3 -3
- package/.docu/lib/{build.impl-AZBZN66Q.js → build.impl-3ZOQORN3.js} +3 -3
- package/.docu/lib/build.node.js +3 -3
- package/.docu/lib/{chunk-IN2QAGDZ.js → chunk-6EOUQCRM.js} +6 -4
- package/.docu/lib/{chunk-HF3KKRQL.js → chunk-6HFBJUMG.js} +2 -2
- package/.docu/lib/{chunk-3LRUTZZD.js → chunk-FERG25YW.js} +37 -13
- package/.docu/lib/{chunk-PGIHPW5L.js → chunk-MQRFIDS4.js} +1 -1
- package/.docu/lib/{chunk-PJVCY4FK.js → chunk-U7M5SK76.js} +1 -1
- package/.docu/lib/{chunk-42JQLAKP.js → chunk-URBATJEC.js} +184 -128
- package/.docu/lib/clean.js +1 -1
- package/.docu/lib/deploy.deno.js +1 -1
- package/.docu/lib/deploy.node.js +1 -1
- package/.docu/lib/preview.deno.js +2 -2
- package/.docu/lib/preview.node.js +2 -2
- package/.docu/lib/server.deno.js +3 -3
- package/.docu/lib/server.node.js +3 -3
- package/.docu/node/build.impl.ts +50 -11
- package/.docu/node/build.ts +50 -11
- package/.docu/node/logger.ts +7 -3
- package/.docu/node/mdx.ts +87 -21
- package/.docu/node/route.ts +27 -19
- package/.docu/node/search-indexer.ts +4 -1
- package/package.json +5 -5
package/.docu/node/build.ts
CHANGED
|
@@ -4,7 +4,16 @@ import { createHash } from "node:crypto";
|
|
|
4
4
|
import { join, dirname } from "node:path";
|
|
5
5
|
import React from "react";
|
|
6
6
|
import { renderToString } from "react-dom/server";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
compileMdx,
|
|
9
|
+
compileMdxModule,
|
|
10
|
+
frontmatterField,
|
|
11
|
+
getGitLastModifiedBatch,
|
|
12
|
+
getPageContent,
|
|
13
|
+
getPageFrontmatter,
|
|
14
|
+
getPageStripped,
|
|
15
|
+
registerPageContent,
|
|
16
|
+
} from "./mdx";
|
|
8
17
|
import {
|
|
9
18
|
DOCS_DIR,
|
|
10
19
|
DIST_DIR,
|
|
@@ -98,7 +107,24 @@ async function renderDocsPage(
|
|
|
98
107
|
try {
|
|
99
108
|
const remarkPlugins = builder?.collectRemarkPlugins();
|
|
100
109
|
const rehypePlugins = builder?.collectRehypePlugins();
|
|
101
|
-
|
|
110
|
+
// Parse-once: reuse the prePass frontmatter + stripped content so the
|
|
111
|
+
// SSR phase does not re-extract them. Only when the prePass actually
|
|
112
|
+
// registered them — otherwise compileMdx does its own extraction.
|
|
113
|
+
const preFm = getPageFrontmatter(`/${slug}`);
|
|
114
|
+
const preStripped = getPageStripped(`/${slug}`);
|
|
115
|
+
const pre =
|
|
116
|
+
preFm !== undefined && preStripped !== undefined
|
|
117
|
+
? { frontmatter: preFm, strippedContent: preStripped }
|
|
118
|
+
: undefined;
|
|
119
|
+
result = await compileMdx(
|
|
120
|
+
content,
|
|
121
|
+
filePath,
|
|
122
|
+
gitDates,
|
|
123
|
+
remarkPlugins,
|
|
124
|
+
rehypePlugins,
|
|
125
|
+
undefined,
|
|
126
|
+
pre
|
|
127
|
+
);
|
|
102
128
|
} catch (err) {
|
|
103
129
|
const msg = err instanceof Error ? err.message : "Unknown MDX error";
|
|
104
130
|
throw new Error(`MDX Error in: docs/${slug}.mdx\n${msg}`, { cause: err });
|
|
@@ -229,6 +255,9 @@ async function build() {
|
|
|
229
255
|
} catch {
|
|
230
256
|
return;
|
|
231
257
|
}
|
|
258
|
+
// Cache the original content so the page loop does not re-read the file
|
|
259
|
+
// (one disk read per file — the frontmatter is parsed once here too).
|
|
260
|
+
registerPageContent(`/${file.path}`, raw);
|
|
232
261
|
let content = raw;
|
|
233
262
|
if (builder) {
|
|
234
263
|
const relPath = file.absPath.replace(PROJECT_ROOT + "/", "");
|
|
@@ -237,7 +266,12 @@ async function build() {
|
|
|
237
266
|
}
|
|
238
267
|
const remarkPlugins = builder?.collectRemarkPlugins();
|
|
239
268
|
const rehypePlugins = builder?.collectRehypePlugins();
|
|
240
|
-
mdxSources[file.path] = await compileMdxModule(
|
|
269
|
+
mdxSources[file.path] = await compileMdxModule(
|
|
270
|
+
content,
|
|
271
|
+
remarkPlugins,
|
|
272
|
+
rehypePlugins,
|
|
273
|
+
`/${file.path}`
|
|
274
|
+
);
|
|
241
275
|
});
|
|
242
276
|
await Promise.all(prePassTasks);
|
|
243
277
|
|
|
@@ -307,12 +341,14 @@ async function build() {
|
|
|
307
341
|
}
|
|
308
342
|
}
|
|
309
343
|
|
|
310
|
-
let rawMdx
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
344
|
+
let rawMdx = getPageContent(`/${file.path}`);
|
|
345
|
+
if (rawMdx === undefined) {
|
|
346
|
+
try {
|
|
347
|
+
rawMdx = await readFile(file.absPath, "utf-8");
|
|
348
|
+
} catch (err) {
|
|
349
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
316
352
|
}
|
|
317
353
|
|
|
318
354
|
if (rebuildDecision === "hash_check") {
|
|
@@ -440,8 +476,11 @@ async function build() {
|
|
|
440
476
|
|
|
441
477
|
logger.indexStart();
|
|
442
478
|
t = performance.now();
|
|
443
|
-
|
|
444
|
-
|
|
479
|
+
// No content changed (all pages cached) → the aggregated index is
|
|
480
|
+
// unchanged too; reuse the existing file instead of regenerating it.
|
|
481
|
+
const indexSkipped = built === 0 && existsSync(join(ASSETS_DIR, "search-index.json"));
|
|
482
|
+
const indexCount = indexSkipped ? 0 : await generateSearchIndex();
|
|
483
|
+
logger.indexDone(indexCount, Math.round(performance.now() - t), indexSkipped);
|
|
445
484
|
|
|
446
485
|
logger.routes();
|
|
447
486
|
console.log("");
|
package/.docu/node/logger.ts
CHANGED
|
@@ -179,9 +179,13 @@ export const logger = {
|
|
|
179
179
|
this.spinner.start("Generating search index...");
|
|
180
180
|
},
|
|
181
181
|
|
|
182
|
-
indexDone(records: number, ms: number) {
|
|
183
|
-
if (guard("info", "index_done", { records, duration_ms: ms })) return;
|
|
184
|
-
this.spinner.stop(
|
|
182
|
+
indexDone(records: number, ms: number, skipped = false) {
|
|
183
|
+
if (guard("info", "index_done", { records, duration_ms: ms, skipped })) return;
|
|
184
|
+
this.spinner.stop(
|
|
185
|
+
skipped
|
|
186
|
+
? `Search index cached ${c.dim}(${ms}ms)${c.reset}`
|
|
187
|
+
: `Search index generated ${c.dim}(${records} records, ${ms}ms)${c.reset}`
|
|
188
|
+
);
|
|
185
189
|
},
|
|
186
190
|
|
|
187
191
|
routes() {
|
package/.docu/node/mdx.ts
CHANGED
|
@@ -115,13 +115,19 @@ export interface MdxResult {
|
|
|
115
115
|
* DocuBook frontmatter contract — single source of truth for frontmatter
|
|
116
116
|
* fields. Add new properties here; types and validation derive from it.
|
|
117
117
|
* YAML coerces unquoted values, so string fields use `z.coerce.*`.
|
|
118
|
+
* `.passthrough()` keeps unknown fields (e.g. `author: wildan`, `tags`)
|
|
119
|
+
* in the parsed output — arbitrary frontmatter metadata stays available
|
|
120
|
+
* via `frontmatterField(frontmatter, key)` instead of being silently
|
|
121
|
+
* stripped by Zod's default object parsing.
|
|
118
122
|
*/
|
|
119
|
-
export const frontmatterSchema = z
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
export const frontmatterSchema = z
|
|
124
|
+
.object({
|
|
125
|
+
title: z.coerce.string().optional(),
|
|
126
|
+
description: z.coerce.string().optional(),
|
|
127
|
+
image: z.coerce.string().optional(),
|
|
128
|
+
date: z.coerce.string().optional(),
|
|
129
|
+
})
|
|
130
|
+
.passthrough();
|
|
125
131
|
|
|
126
132
|
export type Frontmatter = z.infer<typeof frontmatterSchema>;
|
|
127
133
|
|
|
@@ -162,12 +168,13 @@ async function serializeWithDocPlugins(
|
|
|
162
168
|
remarkPlugins?: Pluggable[];
|
|
163
169
|
rehypePlugins?: Pluggable[];
|
|
164
170
|
frontmatterSchema?: FrontmatterSchema;
|
|
165
|
-
} = {}
|
|
171
|
+
} = {},
|
|
172
|
+
pre?: { frontmatter: Frontmatter; strippedContent: string }
|
|
166
173
|
) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
174
|
+
// Parse-once: when the prePass already extracted the frontmatter + stripped
|
|
175
|
+
// content, reuse it instead of re-parsing (the SSR phase skips extraction).
|
|
176
|
+
const { strippedContent, frontmatter } =
|
|
177
|
+
pre ?? extractFrontmatterWithContent<Frontmatter>(rawMdx, opts.frontmatterSchema);
|
|
171
178
|
|
|
172
179
|
const defaultRemark = createDefaultRemarkPlugins();
|
|
173
180
|
const defaultRehype = createDefaultRehypePlugins();
|
|
@@ -179,7 +186,8 @@ async function serializeWithDocPlugins(
|
|
|
179
186
|
const finalRehype = [...defaultRehype, rehypeDocsHtmlLinks, ...(opts.rehypePlugins ?? [])];
|
|
180
187
|
|
|
181
188
|
// v2 contract: plain markdown + directives only — authored JSX tags are
|
|
182
|
-
// not parsed (dropped, content kept as text).
|
|
189
|
+
// not parsed (dropped, content kept as text). Return the frontmatter parsed
|
|
190
|
+
// above — `serialize()` only parses it when `parseFrontmatter` is set.
|
|
183
191
|
return serialize(strippedContent, {
|
|
184
192
|
outputFormat: opts.outputFormat,
|
|
185
193
|
format: "md",
|
|
@@ -187,7 +195,7 @@ async function serializeWithDocPlugins(
|
|
|
187
195
|
rehypePlugins: finalRehype,
|
|
188
196
|
remarkPlugins: finalRemark,
|
|
189
197
|
},
|
|
190
|
-
});
|
|
198
|
+
}).then((serialized) => ({ ...serialized, frontmatter, strippedContent }));
|
|
191
199
|
}
|
|
192
200
|
|
|
193
201
|
/**
|
|
@@ -206,15 +214,19 @@ export async function compileMdx(
|
|
|
206
214
|
gitDates?: Map<string, string>,
|
|
207
215
|
remarkPlugins?: Pluggable[],
|
|
208
216
|
rehypePlugins?: Pluggable[],
|
|
209
|
-
frontmatterSchema?: FrontmatterSchema
|
|
217
|
+
frontmatterSchema?: FrontmatterSchema,
|
|
218
|
+
/** Pre-pass extracted data — avoids re-parsing frontmatter in the SSR phase. */
|
|
219
|
+
pre?: { frontmatter: Frontmatter; strippedContent: string }
|
|
210
220
|
): Promise<MdxResult> {
|
|
211
221
|
const tocs = extractTocsFromRawMdx(rawMdx);
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
222
|
+
const frontmatter =
|
|
223
|
+
pre?.frontmatter ??
|
|
224
|
+
extractFrontmatterWithContent<Frontmatter>(rawMdx, frontmatterSchema).frontmatter;
|
|
225
|
+
const serialized = await serializeWithDocPlugins(
|
|
226
|
+
rawMdx,
|
|
227
|
+
{ remarkPlugins, rehypePlugins, frontmatterSchema },
|
|
228
|
+
pre
|
|
229
|
+
);
|
|
218
230
|
|
|
219
231
|
const components = createMdxComponents();
|
|
220
232
|
const content = React.createElement(MDXRemote, {
|
|
@@ -245,15 +257,69 @@ export async function compileMdx(
|
|
|
245
257
|
* instead of `new Function(compiledSource)`. Uses the same plugin chain as
|
|
246
258
|
* `compileMdx` so the hydrated tree matches the SSR output.
|
|
247
259
|
*/
|
|
260
|
+
/**
|
|
261
|
+
* Frontmatter records collected once during compilation — pagination title /
|
|
262
|
+
* description and other metadata consumers read from here instead of
|
|
263
|
+
* re-reading + re-parsing files (parse-once contract: the frontmatter is
|
|
264
|
+
* already parsed by `serializeWithDocPlugins`).
|
|
265
|
+
*/
|
|
266
|
+
const pageFrontmatter = new Map<string, Frontmatter>();
|
|
267
|
+
|
|
268
|
+
/** Register a page's frontmatter, keyed by its href. */
|
|
269
|
+
export function registerPageFrontmatter(href: string, frontmatter: Frontmatter): void {
|
|
270
|
+
pageFrontmatter.set(href, frontmatter);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/** Look up a page's frontmatter (undefined when not yet compiled). */
|
|
274
|
+
export function getPageFrontmatter(href: string): Frontmatter | undefined {
|
|
275
|
+
return pageFrontmatter.get(href);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Frontmatter-stripped content from the prePass — lets the SSR compile
|
|
280
|
+
* phase skip its own `extractFrontmatterWithContent` (parse-once across
|
|
281
|
+
* both compile phases).
|
|
282
|
+
*/
|
|
283
|
+
const pageStripped = new Map<string, string>();
|
|
284
|
+
|
|
285
|
+
export function registerPageStripped(href: string, stripped: string): void {
|
|
286
|
+
pageStripped.set(href, stripped);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
export function getPageStripped(href: string): string | undefined {
|
|
290
|
+
return pageStripped.get(href);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Original (pre-transform) file content, cached during the prePass so the
|
|
295
|
+
* page loop does not re-read the file from disk — one read per file.
|
|
296
|
+
*/
|
|
297
|
+
const pageContent = new Map<string, string>();
|
|
298
|
+
|
|
299
|
+
export function registerPageContent(href: string, raw: string): void {
|
|
300
|
+
pageContent.set(href, raw);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
export function getPageContent(href: string): string | undefined {
|
|
304
|
+
return pageContent.get(href);
|
|
305
|
+
}
|
|
306
|
+
|
|
248
307
|
export async function compileMdxModule(
|
|
249
308
|
rawMdx: string,
|
|
250
309
|
remarkPlugins?: Pluggable[],
|
|
251
|
-
rehypePlugins?: Pluggable[]
|
|
310
|
+
rehypePlugins?: Pluggable[],
|
|
311
|
+
/** Page href — registers the frontmatter (title/description/image/date)
|
|
312
|
+
* once for pagination and metadata consumers. */
|
|
313
|
+
href?: string
|
|
252
314
|
): Promise<string> {
|
|
253
315
|
const serialized = await serializeWithDocPlugins(rawMdx, {
|
|
254
316
|
outputFormat: "program",
|
|
255
317
|
remarkPlugins,
|
|
256
318
|
rehypePlugins,
|
|
257
319
|
});
|
|
320
|
+
if (href) {
|
|
321
|
+
registerPageFrontmatter(href, serialized.frontmatter as Frontmatter);
|
|
322
|
+
registerPageStripped(href, serialized.strippedContent);
|
|
323
|
+
}
|
|
258
324
|
return serialized.compiledSource;
|
|
259
325
|
}
|
package/.docu/node/route.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { DOCS_DIR } from "./paths";
|
|
|
5
5
|
import { readFileSync } from "node:fs";
|
|
6
6
|
import { join } from "node:path";
|
|
7
7
|
import { extractFrontmatter } from "@docubook/core";
|
|
8
|
+
import { getPageFrontmatter, registerPageFrontmatter } from "./mdx";
|
|
8
9
|
import type { Frontmatter } from "./mdx";
|
|
9
10
|
|
|
10
11
|
const docuConfig = loadDocuConfig();
|
|
@@ -46,29 +47,31 @@ export function getRouteMap(): Map<string, string> {
|
|
|
46
47
|
return map;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
/**
|
|
51
|
+
* Frontmatter for a page — read from the parse-once registry (populated
|
|
52
|
+
* during compilation) instead of re-reading + re-parsing the file. Falls
|
|
53
|
+
* back to a direct read only for pages the dev server has not compiled yet,
|
|
54
|
+
* and caches the result back into the registry.
|
|
55
|
+
*/
|
|
56
|
+
function readPageFrontmatter(href: string): Frontmatter {
|
|
57
|
+
const registered = getPageFrontmatter(href);
|
|
58
|
+
if (registered) return registered;
|
|
59
|
+
|
|
60
|
+
let fm: Frontmatter = {};
|
|
57
61
|
const rel = href.replace(/^\/|$/g, "");
|
|
58
62
|
for (const ext of [".mdx", ".md"]) {
|
|
59
63
|
for (const file of [join(DOCS_DIR, `${rel}${ext}`), join(DOCS_DIR, `${rel}/index${ext}`)]) {
|
|
60
64
|
try {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
if (description) break;
|
|
65
|
+
fm = extractFrontmatter<Frontmatter>(readFileSync(file, "utf-8"));
|
|
66
|
+
break;
|
|
64
67
|
} catch {
|
|
65
68
|
// not this file — try the next candidate
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
|
-
if (
|
|
71
|
+
if (Object.keys(fm).length) break;
|
|
69
72
|
}
|
|
70
|
-
|
|
71
|
-
return
|
|
73
|
+
registerPageFrontmatter(href, fm);
|
|
74
|
+
return fm;
|
|
72
75
|
}
|
|
73
76
|
|
|
74
77
|
export function getPreviousNext(pathname: string) {
|
|
@@ -83,12 +86,13 @@ export function getPreviousNext(pathname: string) {
|
|
|
83
86
|
const routeMap = getRouteMap();
|
|
84
87
|
const first = paths[0];
|
|
85
88
|
if (!first) return { prev: null, next: null };
|
|
89
|
+
const fm = readPageFrontmatter(first);
|
|
86
90
|
return {
|
|
87
91
|
prev: null,
|
|
88
92
|
next: {
|
|
89
93
|
href: first,
|
|
90
|
-
title: routeMap.get(first) || "",
|
|
91
|
-
description:
|
|
94
|
+
title: fm.title || routeMap.get(first) || "",
|
|
95
|
+
description: fm.description || "",
|
|
92
96
|
},
|
|
93
97
|
};
|
|
94
98
|
}
|
|
@@ -105,13 +109,17 @@ export function getPreviousNext(pathname: string) {
|
|
|
105
109
|
const prevHref = index > 0 ? paths[index - 1] : null;
|
|
106
110
|
const nextHref = index < paths.length - 1 ? paths[index + 1] : null;
|
|
107
111
|
|
|
112
|
+
const prevFm = prevHref ? readPageFrontmatter(prevHref) : null;
|
|
113
|
+
const nextFm = nextHref ? readPageFrontmatter(nextHref) : null;
|
|
108
114
|
return {
|
|
109
|
-
prev: prevHref
|
|
115
|
+
prev: prevHref
|
|
116
|
+
? { href: prevHref, title: prevFm?.title || routeMap.get(prevHref) || "" }
|
|
117
|
+
: null,
|
|
110
118
|
next: nextHref
|
|
111
119
|
? {
|
|
112
120
|
href: nextHref,
|
|
113
|
-
title: routeMap.get(nextHref) || "",
|
|
114
|
-
description:
|
|
121
|
+
title: nextFm?.title || routeMap.get(nextHref) || "",
|
|
122
|
+
description: nextFm?.description || "",
|
|
115
123
|
}
|
|
116
124
|
: null,
|
|
117
125
|
};
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
15
15
|
import { resolve, join } from "node:path";
|
|
16
|
+
import { getPageContent } from "./mdx";
|
|
16
17
|
import { extractFrontmatterWithContent } from "@docubook/core";
|
|
17
18
|
import { frontmatterField } from "./mdx";
|
|
18
19
|
import { DOCS_DIR, ASSETS_DIR, loadDocuConfig } from "./paths";
|
|
@@ -193,7 +194,9 @@ export async function generateSearchIndex(docsDir?: string, outputDir?: string):
|
|
|
193
194
|
const mdxFiles = await scanMdxFiles(docs);
|
|
194
195
|
const results = await Promise.all(
|
|
195
196
|
mdxFiles.map(async (file) => {
|
|
196
|
-
|
|
197
|
+
// Parse-once: reuse the prePass-cached raw content when available —
|
|
198
|
+
// no second disk read of every file.
|
|
199
|
+
const raw = getPageContent(`/${file.path}`) ?? (await readFile(file.absPath, "utf-8"));
|
|
197
200
|
return extractRecords(file.path, raw);
|
|
198
201
|
})
|
|
199
202
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docubook/flame",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-beta.1",
|
|
4
4
|
"description": "A blazing-fast React + MDX framework powered by Bun, built for modern documentation experiences.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -56,10 +56,10 @@
|
|
|
56
56
|
"react-dom": "^19.2.7",
|
|
57
57
|
"unified": "^11.0.0",
|
|
58
58
|
"zod": "^4.4.3",
|
|
59
|
-
"@docubook/markdown": "^2.0.0-
|
|
60
|
-
"@docubook/
|
|
61
|
-
"@docubook/
|
|
62
|
-
"@docubook/
|
|
59
|
+
"@docubook/markdown": "^2.0.0-beta.1",
|
|
60
|
+
"@docubook/core": "^2.0.0-beta.0",
|
|
61
|
+
"@docubook/ui-react": "^2.0.0-beta.0",
|
|
62
|
+
"@docubook/themes-colors": "^2.0.0-beta.0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
65
|
"@sentry/bun": "^10.0.0"
|