@docubook/flame 1.4.4 → 1.5.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.
Files changed (53) hide show
  1. package/.docu/lib/build.deno.js +11 -0
  2. package/.docu/lib/build.impl-7KJ4ZTAJ.js +12 -0
  3. package/.docu/lib/build.node.js +10 -0
  4. package/.docu/lib/chunk-7ZEUL6PR.js +383 -0
  5. package/.docu/lib/chunk-AI7QAMMZ.js +2410 -0
  6. package/.docu/lib/chunk-E4OIJWCU.js +368 -0
  7. package/.docu/lib/chunk-IR5TVJOV.js +79 -0
  8. package/.docu/lib/chunk-J5NMYSBJ.js +59 -0
  9. package/.docu/lib/chunk-PTRZ2S2C.js +298 -0
  10. package/.docu/lib/chunk-RE4NGTMT.js +185 -0
  11. package/.docu/lib/chunk-TE52TIEW.js +92 -0
  12. package/.docu/lib/clean.js +32 -0
  13. package/.docu/lib/deploy.deno.js +13 -0
  14. package/.docu/lib/deploy.node.js +10 -0
  15. package/.docu/lib/preview.deno.js +10 -0
  16. package/.docu/lib/preview.node.js +10 -0
  17. package/.docu/lib/server.deno.js +11 -0
  18. package/.docu/lib/server.node.js +11 -0
  19. package/.docu/node/build.deno.ts +7 -0
  20. package/.docu/node/build.impl.ts +416 -0
  21. package/.docu/node/build.node.ts +3 -0
  22. package/.docu/node/deploy.deno.ts +11 -0
  23. package/.docu/node/deploy.node.ts +6 -0
  24. package/.docu/node/deploy.shared.ts +85 -0
  25. package/.docu/node/deploy.ts +11 -0
  26. package/.docu/node/escapeHtml.ts +18 -0
  27. package/.docu/node/git.ts +79 -0
  28. package/.docu/node/html.shared.ts +110 -0
  29. package/.docu/node/hydrate.node.ts +276 -0
  30. package/.docu/node/hydrate.ts +17 -31
  31. package/.docu/node/mdx.ts +1 -1
  32. package/.docu/node/paths.ts +24 -0
  33. package/.docu/node/plugin-builder.ts +6 -2
  34. package/.docu/node/plugin.ts +11 -2
  35. package/.docu/node/preview.deno.ts +4 -0
  36. package/.docu/node/preview.impl.ts +96 -0
  37. package/.docu/node/preview.node.ts +4 -0
  38. package/.docu/node/security.ts +5 -0
  39. package/.docu/node/server-routes.ts +4 -4
  40. package/.docu/node/server.deno.ts +4 -0
  41. package/.docu/node/server.impl.ts +184 -0
  42. package/.docu/node/server.node.ts +4 -0
  43. package/.docu/styles/globals.css +20 -5
  44. package/README.md +57 -506
  45. package/bin/cli.js +99 -14
  46. package/bin/compile-lib.mjs +67 -0
  47. package/package.json +9 -7
  48. package/template/docs/getting-started/configuration.mdx +18 -0
  49. package/template/docs/getting-started/overview.mdx +50 -0
  50. package/template/docs/guide/deployment.mdx +27 -0
  51. package/template/docs/guide/routing.mdx +25 -0
  52. package/template/docs/index.mdx +8 -205
  53. package/template/docu.json +32 -1
@@ -1,6 +1,6 @@
1
1
  import { readFile } from "node:fs/promises";
2
2
  import { resolve } from "node:path";
3
- import { statSync } from "node:fs";
3
+ import { readFileSync, statSync } from "node:fs";
4
4
  import React, { type ReactNode } from "react";
5
5
  import { renderToString } from "react-dom/server";
6
6
  import { compileMdx } from "./mdx";
@@ -14,7 +14,7 @@ import NotFoundPage from "../pages/404";
14
14
  import IndexPage from "../pages/index";
15
15
  import { DocsLayout } from "../components/DocsLayout";
16
16
  import { generateNonce, isPathSafe, isSlugSafe, htmlResponse, SECURITY_HEADERS } from "./security";
17
- import { htmlShell as createHtmlShell, hmrScript, errorHtml } from "./html";
17
+ import { htmlShell as createHtmlShell, hmrScript, errorHtml } from "./html.shared";
18
18
 
19
19
  export interface ServerState {
20
20
  docuConfig: DocuConfig;
@@ -249,7 +249,7 @@ export function serveStatic(pathname: string): Response | null {
249
249
  try {
250
250
  const s = statSync(assetPath);
251
251
  if (s.isFile()) {
252
- return new Response(Bun.file(assetPath), {
252
+ return new Response(readFileSync(assetPath), {
253
253
  headers: { "Content-Type": getContentType(pathname) },
254
254
  });
255
255
  }
@@ -266,7 +266,7 @@ export function serveStatic(pathname: string): Response | null {
266
266
  try {
267
267
  const s = statSync(docsAsset);
268
268
  if (s.isFile()) {
269
- return new Response(Bun.file(docsAsset), {
269
+ return new Response(readFileSync(docsAsset), {
270
270
  headers: { "Content-Type": getContentType(pathname) },
271
271
  });
272
272
  }
@@ -0,0 +1,4 @@
1
+ import { denoAdapter } from "@docubook/runt";
2
+ import { runServer } from "./server.impl";
3
+
4
+ await runServer(denoAdapter);
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Runtime-neutral dev server — mirror of `server.ts` (Bun-only, protected)
3
+ * driven by a `RuntimeAdapter` from `@docubook/runt` instead of `Bun.serve`,
4
+ * with manual route matching instead of `Bun.FileSystemRouter`. The page set
5
+ * is static (`/`, `/docs/[[...slug]]`, `/404`), so a router is unnecessary.
6
+ */
7
+
8
+ import { watch } from "node:fs";
9
+ import type { RuntimeAdapter, ServerHandle } from "@docubook/runt";
10
+ import { DOCS_DIR, loadDocuConfig } from "./paths";
11
+ import { loadPlugins } from "./plugin-loader";
12
+ import { BuildPluginBuilder } from "./plugin-builder";
13
+ import { buildClientBundle, computeInlineThemeCss } from "./hydrate.node";
14
+ import { generateSearchIndex } from "./search-indexer";
15
+ import { logger } from "./logger";
16
+ import { initSentry, captureException } from "./sentry";
17
+ import {
18
+ serveStatic,
19
+ handleDocsIndex,
20
+ handleDocsRoute,
21
+ handleIndex,
22
+ handleNotFound,
23
+ serverErrorResponse,
24
+ type ServerState,
25
+ } from "./server-routes";
26
+ import { wrapPluginResponse } from "./security";
27
+ import { stripDocsHtmlSuffix } from "./utils";
28
+
29
+ export async function runServer(adapter: RuntimeAdapter): Promise<ServerHandle> {
30
+ const docuConfig = loadDocuConfig();
31
+
32
+ const parsedPort = parseInt(process.env.PORT ?? "3000", 10);
33
+ const PORT =
34
+ Number.isInteger(parsedPort) && parsedPort > 0 && parsedPort <= 65535 ? parsedPort : 3000;
35
+
36
+ logger.buildStart();
37
+
38
+ await initSentry();
39
+
40
+ logger.bundleStart();
41
+ let t = performance.now();
42
+ const assetManifest = await buildClientBundle();
43
+ logger.bundleDone(Math.round(performance.now() - t));
44
+
45
+ const inlineThemeCss = computeInlineThemeCss();
46
+
47
+ logger.indexStart();
48
+ t = performance.now();
49
+ const records = await generateSearchIndex();
50
+ logger.indexDone(records, Math.round(performance.now() - t));
51
+
52
+ logger.routes();
53
+
54
+ // Plugin setup — all hooks active (onLoad, remark/rehype, frontmatter, head/body, html transform, handleRequest)
55
+ const pluginsConfig = docuConfig.plugins ?? [];
56
+ const builder = pluginsConfig.length > 0 ? new BuildPluginBuilder(docuConfig) : null;
57
+
58
+ if (builder) {
59
+ const plugins = await loadPlugins(pluginsConfig);
60
+
61
+ for (const plugin of plugins) {
62
+ await plugin.setup(builder);
63
+ }
64
+ }
65
+
66
+ const state: ServerState = {
67
+ docuConfig,
68
+ assetManifest,
69
+ inlineThemeCss,
70
+ builder,
71
+ };
72
+
73
+ const hmrClients = new Set<ReadableStreamDefaultController>();
74
+
75
+ let hmrTimeout: ReturnType<typeof setTimeout> | null = null;
76
+ const watcher = watch(DOCS_DIR, { recursive: true }, (_event, filename) => {
77
+ if (!filename || (!filename.endsWith(".mdx") && !filename.endsWith(".md"))) return;
78
+ if (hmrTimeout) clearTimeout(hmrTimeout);
79
+ hmrTimeout = setTimeout(() => {
80
+ for (const client of [...hmrClients]) {
81
+ try {
82
+ client.enqueue(new TextEncoder().encode("data: reload\n\n"));
83
+ } catch {
84
+ hmrClients.delete(client);
85
+ }
86
+ }
87
+ }, 300);
88
+ });
89
+
90
+ process.on("SIGINT", () => {
91
+ watcher.close();
92
+ process.exit(0);
93
+ });
94
+ process.on("SIGTERM", () => {
95
+ watcher.close();
96
+ process.exit(0);
97
+ });
98
+
99
+ let handle: ServerHandle | null = null;
100
+
101
+ const fetchHandler = async (req: Request): Promise<Response> => {
102
+ const url = new URL(req.url);
103
+ // Generated links carry `.html` (matching the static build output);
104
+ // route them to the same handler as their extensionless form.
105
+ const pathname = stripDocsHtmlSuffix(url.pathname);
106
+ const startTime = performance.now();
107
+
108
+ if (builder) {
109
+ const pluginResponse = await builder.runHandleRequest(req, {
110
+ port: handle?.port ?? PORT,
111
+ hostname: handle?.hostname ?? "localhost",
112
+ });
113
+ if (pluginResponse) {
114
+ const securedResponse = wrapPluginResponse(pluginResponse, true);
115
+ logger.request(
116
+ req.method,
117
+ pathname,
118
+ securedResponse.status,
119
+ Math.round(performance.now() - startTime)
120
+ );
121
+ return securedResponse;
122
+ }
123
+ }
124
+
125
+ try {
126
+ if (pathname === "/__hmr") {
127
+ const stream = new ReadableStream({
128
+ start(controller) {
129
+ hmrClients.add(controller);
130
+ controller.enqueue(new TextEncoder().encode("data: connected\n\n"));
131
+ },
132
+ cancel(controller) {
133
+ hmrClients.delete(controller);
134
+ },
135
+ });
136
+ return new Response(stream, {
137
+ headers: {
138
+ "Content-Type": "text/event-stream",
139
+ "Cache-Control": "no-cache",
140
+ Connection: "keep-alive",
141
+ },
142
+ });
143
+ }
144
+
145
+ if (pathname.startsWith("/assets/") || /\.\w+$/.test(pathname)) {
146
+ const staticRes = serveStatic(pathname);
147
+ if (staticRes) return staticRes;
148
+ }
149
+
150
+ let response: Response;
151
+
152
+ // Manual route matching — same routes Bun.FileSystemRouter derives
153
+ // from `.docu/pages/` ("/", "/docs/[[...slug]]", "/404").
154
+ if (pathname === "/") {
155
+ response = handleIndex(state);
156
+ } else if (pathname === "/docs" || pathname === "/docs/") {
157
+ response = await handleDocsIndex(state);
158
+ } else if (pathname.startsWith("/docs/")) {
159
+ const slug = pathname.slice("/docs/".length).split("/").filter(Boolean);
160
+ response =
161
+ slug.length === 0 ? await handleDocsIndex(state) : await handleDocsRoute(slug, state);
162
+ } else {
163
+ response = handleNotFound(state);
164
+ }
165
+
166
+ logger.request(
167
+ req.method,
168
+ pathname,
169
+ response.status,
170
+ Math.round(performance.now() - startTime)
171
+ );
172
+ return response;
173
+ } catch (err) {
174
+ captureException(err, { method: req.method, pathname });
175
+ logger.request(req.method, pathname, 500, Math.round(performance.now() - startTime));
176
+ return serverErrorResponse(err);
177
+ }
178
+ };
179
+
180
+ handle = await adapter.serve(fetchHandler, { port: PORT, idleTimeout: 255 });
181
+
182
+ logger.ready(handle.port, true);
183
+ return handle;
184
+ }
@@ -0,0 +1,4 @@
1
+ import { nodeAdapter } from "@docubook/runt";
2
+ import { runServer } from "./server.impl";
3
+
4
+ await runServer(nodeAdapter);
@@ -1,10 +1,25 @@
1
- @import "daisyui/daisyui.css";
2
- @import "@docubook/mdx-content/styles.css";
3
1
  @import "tailwindcss";
2
+ @import "@docubook/mdx-content/styles.css";
4
3
 
4
+ @plugin "daisyui" {
5
+ themes:
6
+ light --default,
7
+ dark;
8
+ }
5
9
  @plugin "@tailwindcss/typography";
6
10
  @source "../../.docu/components";
7
11
  @source "../../.docu/pages";
12
+ @source inline("breadcrumbs collapse collapse-open collapse-close collapse-arrow collapse-plus collapse-title collapse-content");
13
+ @source inline("modal modal-top modal-middle modal-bottom modal-box modal-backdrop");
14
+ @source inline("drawer drawer-end drawer-toggle drawer-side drawer-overlay drawer-content");
15
+ @source inline("sm:drawer-open md:drawer-open lg:drawer-open xl:drawer-open");
16
+ @source inline("navbar menu menu-horizontal");
17
+ @source inline("kbd kbd-xs kbd-sm kbd-md kbd-lg kbd-xl");
18
+ @source inline("toggle theme-controller toggle-xs toggle-sm toggle-md toggle-lg");
19
+ @source inline("toggle-primary toggle-secondary toggle-accent toggle-neutral toggle-success toggle-warning toggle-info toggle-error");
20
+ @source inline("input input-ghost input-xs input-sm input-md input-lg input-xl");
21
+ @source inline("input-primary input-secondary input-accent input-neutral input-success input-warning input-info input-error");
22
+ @source inline("label");
8
23
 
9
24
  @custom-variant dark (&:is(.dark *));
10
25
 
@@ -13,7 +28,7 @@
13
28
  --color-base-200: oklch(var(--base-200, 100% 0 0));
14
29
  --color-base-300: oklch(var(--base-300, 100% 0 0));
15
30
  --color-base-content: oklch(var(--base-content, 100% 0 0));
16
- --color-border: hsl(var(--border));
31
+ --color-border: hsl(var(--border-color));
17
32
  --color-input: hsl(var(--input));
18
33
  --color-ring: hsl(var(--ring));
19
34
  --color-background: hsl(var(--background));
@@ -80,7 +95,7 @@
80
95
  --accent-foreground: 0 0% 100%;
81
96
  --destructive: 0 85% 60%;
82
97
  --destructive-foreground: 0 0% 100%;
83
- --border: 210 20% 85%;
98
+ --border-color: 210 20% 85%;
84
99
  --input: 210 20% 85%;
85
100
  --ring: 210 81% 56%;
86
101
  --radius: 0.5rem;
@@ -107,7 +122,7 @@
107
122
  --accent-foreground: 0 0% 100%;
108
123
  --destructive: 0 80% 65%;
109
124
  --destructive-foreground: 0 0% 100%;
110
- --border: 220 10% 28%;
125
+ --border-color: 220 10% 28%;
111
126
  --input: 220 10% 28%;
112
127
  --ring: 210 100% 67%;
113
128
  --radius: 0.5rem;