@docubook/flame 1.5.0 → 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.
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  runBuildCli
3
- } from "./chunk-654THQOR.js";
4
- import "./chunk-2QHMGZIL.js";
3
+ } from "./chunk-E4OIJWCU.js";
4
+ import "./chunk-AI7QAMMZ.js";
5
5
  import "./chunk-RE4NGTMT.js";
6
- import "./chunk-HH4YXWEF.js";
6
+ import "./chunk-PTRZ2S2C.js";
7
7
  import "./chunk-J5NMYSBJ.js";
8
8
 
9
9
  // .docu/node/build.deno.ts
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  runBuild,
3
3
  runBuildCli
4
- } from "./chunk-654THQOR.js";
5
- import "./chunk-2QHMGZIL.js";
4
+ } from "./chunk-E4OIJWCU.js";
5
+ import "./chunk-AI7QAMMZ.js";
6
6
  import "./chunk-RE4NGTMT.js";
7
- import "./chunk-HH4YXWEF.js";
7
+ import "./chunk-PTRZ2S2C.js";
8
8
  import "./chunk-J5NMYSBJ.js";
9
9
  export {
10
10
  runBuild,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  runBuildCli
3
- } from "./chunk-654THQOR.js";
4
- import "./chunk-2QHMGZIL.js";
3
+ } from "./chunk-E4OIJWCU.js";
4
+ import "./chunk-AI7QAMMZ.js";
5
5
  import "./chunk-RE4NGTMT.js";
6
- import "./chunk-HH4YXWEF.js";
6
+ import "./chunk-PTRZ2S2C.js";
7
7
  import "./chunk-J5NMYSBJ.js";
8
8
 
9
9
  // .docu/node/build.node.ts
@@ -14,7 +14,7 @@ import {
14
14
  htmlShell,
15
15
  initSentry,
16
16
  loadPlugins
17
- } from "./chunk-2QHMGZIL.js";
17
+ } from "./chunk-AI7QAMMZ.js";
18
18
  import {
19
19
  SECURITY_HEADERS,
20
20
  generateNonce,
@@ -27,7 +27,7 @@ import {
27
27
  } from "./chunk-RE4NGTMT.js";
28
28
  import {
29
29
  logger
30
- } from "./chunk-HH4YXWEF.js";
30
+ } from "./chunk-PTRZ2S2C.js";
31
31
  import {
32
32
  DIST_DIR,
33
33
  DOCS_DIR,
@@ -847,15 +847,6 @@ async function buildClientBundle() {
847
847
  return { contents: JSON.stringify(resolved), loader: "json" };
848
848
  });
849
849
  }
850
- },
851
- {
852
- name: "mdx-jsx-runtime",
853
- setup(build2) {
854
- build2.onLoad({ filter: /next-mdx-remote[/\\].*jsx-runtime/ }, () => {
855
- const source = nodeEnv === "production" ? `module.exports.jsxRuntime = require("react/jsx-runtime");` : `module.exports.jsxRuntime = require("react/jsx-dev-runtime");`;
856
- return { contents: source, loader: "js" };
857
- });
858
- }
859
850
  }
860
851
  ]
861
852
  });
@@ -13,14 +13,14 @@ import {
13
13
  htmlShell,
14
14
  initSentry,
15
15
  loadPlugins
16
- } from "./chunk-2QHMGZIL.js";
16
+ } from "./chunk-AI7QAMMZ.js";
17
17
  import {
18
18
  generateNonce,
19
19
  scanMdxFiles
20
20
  } from "./chunk-RE4NGTMT.js";
21
21
  import {
22
22
  logger
23
- } from "./chunk-HH4YXWEF.js";
23
+ } from "./chunk-PTRZ2S2C.js";
24
24
  import {
25
25
  ASSETS_DIR,
26
26
  CACHE_FILE,
@@ -32,99 +32,12 @@ import {
32
32
  } from "./chunk-J5NMYSBJ.js";
33
33
 
34
34
  // .docu/node/build.impl.ts
35
- import { readFile, writeFile, mkdir, readdir as readdir2, copyFile } from "node:fs/promises";
36
- import { existsSync as existsSync2 } from "node:fs";
35
+ import { readFile, writeFile, mkdir, readdir, copyFile } from "node:fs/promises";
36
+ import { existsSync } from "node:fs";
37
37
  import { createHash } from "node:crypto";
38
- import { join as join2, dirname } from "node:path";
38
+ import { join, dirname } from "node:path";
39
39
  import React from "react";
40
40
  import { renderToString } from "react-dom/server";
41
-
42
- // .docu/node/build-summary.ts
43
- import { readdir, stat } from "node:fs/promises";
44
- import { join, relative, extname } from "node:path";
45
- import { existsSync } from "node:fs";
46
- var MAX_FILES_SHOWN = 10;
47
- var SEP = "\u2500".repeat(60);
48
- function formatSize(bytes) {
49
- if (bytes < 1024) return `${bytes} B`;
50
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
51
- return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
52
- }
53
- async function walkFiles(dir) {
54
- const out = [];
55
- const entries = await readdir(dir, { withFileTypes: true });
56
- for (const entry of entries) {
57
- const full = join(dir, entry.name);
58
- if (entry.isDirectory()) {
59
- out.push(...await walkFiles(full));
60
- } else if (entry.isFile()) {
61
- const s = await stat(full);
62
- out.push({ path: full, size: s.size });
63
- }
64
- }
65
- return out;
66
- }
67
- async function collectBuildOutput(distDir) {
68
- if (!existsSync(distDir)) return null;
69
- const all = await walkFiles(distDir);
70
- if (all.length === 0) return null;
71
- const files = all.map((f) => ({ path: relative(distDir, f.path), size: f.size })).sort((a, b) => b.size !== a.size ? b.size - a.size : a.path.localeCompare(b.path));
72
- const byExt = /* @__PURE__ */ new Map();
73
- for (const f of files) {
74
- const ext = extname(f.path) || "(none)";
75
- const entry = byExt.get(ext) ?? { ext, count: 0, size: 0 };
76
- entry.count++;
77
- entry.size += f.size;
78
- byExt.set(ext, entry);
79
- }
80
- const byType = [...byExt.values()].sort(
81
- (a, b) => b.size !== a.size ? b.size - a.size : b.count - a.count
82
- );
83
- return {
84
- files,
85
- byType,
86
- totalFiles: files.length,
87
- totalSize: files.reduce((sum, f) => sum + f.size, 0)
88
- };
89
- }
90
- function formatBuildSummary(output) {
91
- const lines = [];
92
- lines.push("\u{1F4E6} Build Output Summary:");
93
- lines.push(SEP);
94
- const shown = output.files.slice(0, MAX_FILES_SHOWN);
95
- const nameWidth = Math.min(Math.max(...shown.map((f) => f.path.length), 1), 50);
96
- for (const f of shown) {
97
- lines.push(` ${f.path.padEnd(nameWidth)} ${formatSize(f.size).padStart(10)}`);
98
- }
99
- const remaining = output.totalFiles - shown.length;
100
- if (remaining > 0) {
101
- lines.push(` ... and ${remaining} more file${remaining === 1 ? "" : "s"}`);
102
- }
103
- lines.push(SEP);
104
- lines.push("\u{1F4CA} Summary by Type:");
105
- const extWidth = Math.max(...output.byType.map((t) => t.ext.length), 1);
106
- for (const t of output.byType) {
107
- const plural = t.count === 1 ? "file" : "files";
108
- lines.push(
109
- ` ${t.ext.padEnd(extWidth)} ${String(t.count).padStart(3)} ${plural} ${formatSize(
110
- t.size
111
- ).padStart(10)}`
112
- );
113
- }
114
- lines.push(SEP);
115
- const totalPlural = output.totalFiles === 1 ? "file" : "files";
116
- lines.push(
117
- `\u{1F4C8} Total: ${output.totalFiles} ${totalPlural} ${formatSize(output.totalSize).padStart(10)}`
118
- );
119
- lines.push(SEP);
120
- return lines.join("\n");
121
- }
122
- async function generateBuildSummary(distDir) {
123
- const output = await collectBuildOutput(distDir);
124
- return output ? formatBuildSummary(output) : null;
125
- }
126
-
127
- // .docu/node/build.impl.ts
128
41
  function parseArgs() {
129
42
  const args = process.argv.slice(2);
130
43
  return {
@@ -137,7 +50,7 @@ function hashContent(content) {
137
50
  }
138
51
  async function readCache() {
139
52
  try {
140
- if (existsSync2(CACHE_FILE)) {
53
+ if (existsSync(CACHE_FILE)) {
141
54
  const data = await readFile(CACHE_FILE, "utf-8");
142
55
  return JSON.parse(data);
143
56
  }
@@ -229,12 +142,12 @@ ${msg}`, { cause: err });
229
142
  return html;
230
143
  }
231
144
  async function copyDirectoryRecursive(src, dest) {
232
- if (!existsSync2(src)) return;
145
+ if (!existsSync(src)) return;
233
146
  await mkdir(dest, { recursive: true });
234
- const entries = await readdir2(src, { withFileTypes: true });
147
+ const entries = await readdir(src, { withFileTypes: true });
235
148
  for (const entry of entries) {
236
- const srcPath = join2(src, entry.name);
237
- const destPath = join2(dest, entry.name);
149
+ const srcPath = join(src, entry.name);
150
+ const destPath = join(dest, entry.name);
238
151
  if (entry.isDirectory()) {
239
152
  await copyDirectoryRecursive(srcPath, destPath);
240
153
  } else {
@@ -256,7 +169,7 @@ async function runBuild() {
256
169
  }
257
170
  await mkdir(DIST_DIR, { recursive: true });
258
171
  await mkdir(ASSETS_DIR, { recursive: true });
259
- await copyDirectoryRecursive(DOCS_ASSETS_DIR, join2(DIST_DIR, "docs", "assets"));
172
+ await copyDirectoryRecursive(DOCS_ASSETS_DIR, join(DIST_DIR, "docs", "assets"));
260
173
  const mdxFiles = await scanMdxFiles(DOCS_DIR);
261
174
  const cache = args.force ? {} : await readCache();
262
175
  let built = 0;
@@ -287,8 +200,8 @@ async function runBuild() {
287
200
  logger.spinner.start("Building pages...");
288
201
  t = performance.now();
289
202
  const allRelPaths = mdxFiles.map((f) => f.absPath.replace(PROJECT_ROOT + "/", ""));
290
- const indexMdxFull = join2(DOCS_DIR, "index.mdx");
291
- if (existsSync2(indexMdxFull)) {
203
+ const indexMdxFull = join(DOCS_DIR, "index.mdx");
204
+ if (existsSync(indexMdxFull)) {
292
205
  allRelPaths.push(indexMdxFull.replace(PROJECT_ROOT + "/", ""));
293
206
  }
294
207
  const gitDates = await getGitLastModifiedBatch(allRelPaths);
@@ -298,8 +211,8 @@ async function runBuild() {
298
211
  for (const file of mdxFiles) {
299
212
  const rebuildDecision = shouldRebuild(file.path, file.mtime, cache);
300
213
  if (rebuildDecision === "no") {
301
- const outputPath = join2(DIST_DIR, "docs", `${file.path}.html`);
302
- if (existsSync2(outputPath) && !assetsChanged) {
214
+ const outputPath = join(DIST_DIR, "docs", `${file.path}.html`);
215
+ if (existsSync(outputPath) && !assetsChanged) {
303
216
  skipped++;
304
217
  continue;
305
218
  }
@@ -316,8 +229,8 @@ async function runBuild() {
316
229
  const cached = cache[file.path];
317
230
  if (cached && cached.hash === contentHash) {
318
231
  if (!assetsChanged) {
319
- const outputPath = join2(DIST_DIR, "docs", `${file.path}.html`);
320
- if (existsSync2(outputPath)) {
232
+ const outputPath = join(DIST_DIR, "docs", `${file.path}.html`);
233
+ if (existsSync(outputPath)) {
321
234
  cache[file.path] = { ...cached, mtime: file.mtime, builtAt: Date.now() };
322
235
  skipped++;
323
236
  continue;
@@ -340,7 +253,7 @@ async function runBuild() {
340
253
  builder,
341
254
  pageNonce
342
255
  );
343
- const outputPath = join2(DIST_DIR, "docs", `${capturedFile.path}.html`);
256
+ const outputPath = join(DIST_DIR, "docs", `${capturedFile.path}.html`);
344
257
  await mkdir(dirname(outputPath), { recursive: true });
345
258
  await writeFile(outputPath, html);
346
259
  cache[capturedFile.path] = {
@@ -362,7 +275,7 @@ async function runBuild() {
362
275
  await Promise.all(buildTasks.slice(i, i + CONCURRENCY).map((fn) => fn()));
363
276
  }
364
277
  try {
365
- const indexMdxPath = join2(DOCS_DIR, "index.mdx");
278
+ const indexMdxPath = join(DOCS_DIR, "index.mdx");
366
279
  const indexRaw = await readFile(indexMdxPath, "utf-8");
367
280
  const indexRelPath = indexMdxPath.replace(PROJECT_ROOT + "/", "");
368
281
  const indexHtml = await renderDocsPage(
@@ -374,8 +287,8 @@ async function runBuild() {
374
287
  builder,
375
288
  generateNonce()
376
289
  );
377
- await mkdir(join2(DIST_DIR, "docs"), { recursive: true });
378
- await writeFile(join2(DIST_DIR, "docs", "index.html"), indexHtml);
290
+ await mkdir(join(DIST_DIR, "docs"), { recursive: true });
291
+ await writeFile(join(DIST_DIR, "docs", "index.html"), indexHtml);
379
292
  } catch (err) {
380
293
  const msg = err instanceof Error ? err.message : String(err);
381
294
  errors.push(`index.mdx: ${msg}`);
@@ -395,7 +308,7 @@ async function runBuild() {
395
308
  nonce: generateNonce(),
396
309
  themeCss: inlineThemeCss
397
310
  });
398
- await writeFile(join2(DIST_DIR, "index.html"), landingHtml);
311
+ await writeFile(join(DIST_DIR, "index.html"), landingHtml);
399
312
  const notFoundPage = React.createElement(
400
313
  DocsLayout,
401
314
  { repoUrl: docuConfig.repo?.url },
@@ -412,7 +325,7 @@ async function runBuild() {
412
325
  nonce: generateNonce(),
413
326
  themeCss: inlineThemeCss
414
327
  });
415
- await writeFile(join2(DIST_DIR, "404.html"), notFoundHtml);
328
+ await writeFile(join(DIST_DIR, "404.html"), notFoundHtml);
416
329
  logger.spinner.stop(
417
330
  `Built ${built} pages (${skipped} cached) \x1B[90m(${Math.round(performance.now() - t)}ms)\x1B[0m`
418
331
  );
@@ -420,8 +333,8 @@ async function runBuild() {
420
333
  const pages = mdxFiles.map((f) => ({
421
334
  slug: f.path,
422
335
  title: f.path.split("/").pop() || f.path,
423
- filePath: join2(DOCS_DIR, f.path),
424
- outputPath: join2(DIST_DIR, "docs", `${f.path}.html`)
336
+ filePath: join(DOCS_DIR, f.path),
337
+ outputPath: join(DIST_DIR, "docs", `${f.path}.html`)
425
338
  }));
426
339
  await builder.runOnEnd(pages);
427
340
  }
@@ -430,12 +343,6 @@ async function runBuild() {
430
343
  const indexCount = await generateSearchIndex();
431
344
  logger.indexDone(indexCount, Math.round(performance.now() - t));
432
345
  logger.routes();
433
- console.log("");
434
- const buildSummary = await generateBuildSummary(DIST_DIR);
435
- if (buildSummary) {
436
- console.log(buildSummary);
437
- console.log("");
438
- }
439
346
  await writeCache(cache);
440
347
  if (errors.length > 0) {
441
348
  console.error(`
@@ -12,7 +12,7 @@ var WORKFLOW_FILE = join(WORKFLOW_DIR, "deploy.yml");
12
12
  async function runDeploy() {
13
13
  console.log("\u{1F4E6} Building for production...\n");
14
14
  process.env.NODE_ENV = "production";
15
- const { runBuildCli } = await import("./build.impl-ST63VRTV.js");
15
+ const { runBuildCli } = await import("./build.impl-7KJ4ZTAJ.js");
16
16
  await runBuildCli();
17
17
  await writeFile(join(DIST_DIR, ".nojekyll"), "");
18
18
  if (!existsSync(WORKFLOW_FILE)) {
@@ -5,7 +5,7 @@ import {
5
5
  // package.json
6
6
  var package_default = {
7
7
  name: "@docubook/flame",
8
- version: "1.5.0",
8
+ version: "1.5.1",
9
9
  description: "A blazing-fast React + MDX framework powered by Bun, built for modern documentation experiences.",
10
10
  type: "module",
11
11
  bin: {
@@ -89,13 +89,11 @@ var package_default = {
89
89
  "@types/node": "^22.0.0",
90
90
  "@types/react": "^19.0.0",
91
91
  "@types/react-dom": "^19.0.0",
92
- autoprefixer: "^10.4.0",
93
92
  "bun-types": "^1.3.0",
94
93
  eslint: "^10.3.0",
95
94
  "eslint-plugin-perfectionist": "^5.9.0",
96
95
  "eslint-plugin-react": "^7.37.5",
97
96
  "eslint-plugin-react-hooks": "^7.1.1",
98
- postcss: "^8.4.0",
99
97
  tailwindcss: "^4.3.0",
100
98
  typescript: "^5.9.3",
101
99
  "typescript-eslint": "^8.59.2"
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-RE4NGTMT.js";
8
8
  import {
9
9
  logger
10
- } from "./chunk-HH4YXWEF.js";
10
+ } from "./chunk-PTRZ2S2C.js";
11
11
  import {
12
12
  DIST_DIR
13
13
  } from "./chunk-J5NMYSBJ.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  logger
3
- } from "./chunk-HH4YXWEF.js";
3
+ } from "./chunk-PTRZ2S2C.js";
4
4
  import "./chunk-J5NMYSBJ.js";
5
5
 
6
6
  // .docu/node/clean.ts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runDeploy
3
- } from "./chunk-C6RZ2KBH.js";
3
+ } from "./chunk-IR5TVJOV.js";
4
4
  import "./chunk-J5NMYSBJ.js";
5
5
 
6
6
  // .docu/node/deploy.deno.ts
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  runDeploy
3
- } from "./chunk-C6RZ2KBH.js";
3
+ } from "./chunk-IR5TVJOV.js";
4
4
  import "./chunk-J5NMYSBJ.js";
5
5
 
6
6
  // .docu/node/deploy.node.ts
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  runPreview
3
- } from "./chunk-ZOWTASXL.js";
3
+ } from "./chunk-TE52TIEW.js";
4
4
  import "./chunk-RE4NGTMT.js";
5
- import "./chunk-HH4YXWEF.js";
5
+ import "./chunk-PTRZ2S2C.js";
6
6
  import "./chunk-J5NMYSBJ.js";
7
7
 
8
8
  // .docu/node/preview.deno.ts
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  runPreview
3
- } from "./chunk-ZOWTASXL.js";
3
+ } from "./chunk-TE52TIEW.js";
4
4
  import "./chunk-RE4NGTMT.js";
5
- import "./chunk-HH4YXWEF.js";
5
+ import "./chunk-PTRZ2S2C.js";
6
6
  import "./chunk-J5NMYSBJ.js";
7
7
 
8
8
  // .docu/node/preview.node.ts
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  runServer
3
- } from "./chunk-X6GYOIYZ.js";
4
- import "./chunk-2QHMGZIL.js";
3
+ } from "./chunk-7ZEUL6PR.js";
4
+ import "./chunk-AI7QAMMZ.js";
5
5
  import "./chunk-RE4NGTMT.js";
6
- import "./chunk-HH4YXWEF.js";
6
+ import "./chunk-PTRZ2S2C.js";
7
7
  import "./chunk-J5NMYSBJ.js";
8
8
 
9
9
  // .docu/node/server.deno.ts
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  runServer
3
- } from "./chunk-X6GYOIYZ.js";
4
- import "./chunk-2QHMGZIL.js";
3
+ } from "./chunk-7ZEUL6PR.js";
4
+ import "./chunk-AI7QAMMZ.js";
5
5
  import "./chunk-RE4NGTMT.js";
6
- import "./chunk-HH4YXWEF.js";
6
+ import "./chunk-PTRZ2S2C.js";
7
7
  import "./chunk-J5NMYSBJ.js";
8
8
 
9
9
  // .docu/node/server.node.ts
@@ -26,7 +26,6 @@ import { htmlShell } from "./html.shared";
26
26
  import { generateSearchIndex } from "./search-indexer";
27
27
  import { buildClientBundle, computeInlineThemeCss } from "./hydrate.node";
28
28
  import { logger } from "./logger";
29
- import { generateBuildSummary } from "./build-summary";
30
29
  import { initSentry, captureException } from "./sentry";
31
30
  import { loadPlugins } from "./plugin-loader";
32
31
  import { BuildPluginBuilder } from "./plugin-builder";
@@ -396,13 +395,6 @@ export async function runBuild(): Promise<void> {
396
395
  logger.indexDone(indexCount, Math.round(performance.now() - t));
397
396
 
398
397
  logger.routes();
399
- console.log("");
400
-
401
- const buildSummary = await generateBuildSummary(DIST_DIR);
402
- if (buildSummary) {
403
- console.log(buildSummary);
404
- console.log("");
405
- }
406
398
 
407
399
  await writeCache(cache);
408
400
 
@@ -226,18 +226,7 @@ export async function buildClientBundle(): Promise<{ js: string; css: string }>
226
226
  });
227
227
  },
228
228
  },
229
- {
230
- name: "mdx-jsx-runtime",
231
- setup(build) {
232
- build.onLoad({ filter: /next-mdx-remote[/\\].*jsx-runtime/ }, () => {
233
- const source =
234
- nodeEnv === "production"
235
- ? `module.exports.jsxRuntime = require("react/jsx-runtime");`
236
- : `module.exports.jsxRuntime = require("react/jsx-dev-runtime");`;
237
- return { contents: source, loader: "js" };
238
- });
239
- },
240
- },
229
+
241
230
  ],
242
231
  });
243
232
  } finally {
@@ -92,18 +92,7 @@ export async function buildClientBundle(): Promise<{ js: string; css: string }>
92
92
  });
93
93
  },
94
94
  },
95
- {
96
- name: "mdx-jsx-runtime",
97
- setup(build) {
98
- build.onLoad({ filter: /next-mdx-remote[/\\].*jsx-runtime/ }, () => {
99
- const source =
100
- nodeEnv === "production"
101
- ? `module.exports.jsxRuntime = require("react/jsx-runtime");`
102
- : `module.exports.jsxRuntime = require("react/jsx-dev-runtime");`;
103
- return { contents: source, loader: "js" };
104
- });
105
- },
106
- },
95
+
107
96
  ],
108
97
  });
109
98
 
package/bin/cli.js CHANGED
@@ -9,9 +9,13 @@ import { spawnSync } from "node:child_process";
9
9
  const __dirname = import.meta.dirname;
10
10
 
11
11
  // Runtime detection — override with FLAME_RUNTIME=bun|node|deno for testing.
12
+ // Deno's npm compat layer may expose `Bun` via globals, check execPath first.
12
13
  const runtime =
13
14
  process.env.FLAME_RUNTIME ||
14
- (typeof Bun !== "undefined" ? "bun" : typeof Deno !== "undefined" ? "deno" : "node");
15
+ (process.execPath.includes("deno") ? "deno" :
16
+ typeof Bun !== "undefined" ? "bun" :
17
+ typeof Deno !== "undefined" ? "deno" :
18
+ "node");
15
19
 
16
20
  const COMMAND_MAP = {
17
21
  bun: {
@@ -107,13 +111,19 @@ if (command === "init") {
107
111
  preview: `${flameCmd} preview`,
108
112
  deploy: `${flameCmd} deploy`,
109
113
  };
114
+
115
+ // Generate deno.json with nodeModulesDir for npm compat.
116
+ const denoConfig = {
117
+ nodeModulesDir: "auto",
118
+ };
119
+ writeFileSync(join(targetDir, "deno.json"), JSON.stringify(denoConfig, null, 2) + "\n");
110
120
  }
111
121
  writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
112
122
 
113
123
  const nextSteps = {
114
124
  bun: " bun install\n bun run dev",
115
125
  node: " npm install\n npm run dev",
116
- deno: " deno task dev",
126
+ deno: " deno task dev\n\n ⚠️ If you see a freshness error, run:\n DENO_ALLOW_NEWER=true deno task dev",
117
127
  }[runtime];
118
128
  console.log(`\n ✓ Project scaffolded!\n\n Next steps:\n${nextSteps}\n`);
119
129
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docubook/flame",
3
- "version": "1.5.0",
3
+ "version": "1.5.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": {
@@ -54,8 +54,8 @@
54
54
  "react": "^19.2.7",
55
55
  "react-dom": "^19.2.7",
56
56
  "unified": "^11.0.0",
57
- "@docubook/core": "^1.8.1",
58
- "@docubook/mdx-content": "^3.4.2",
57
+ "@docubook/core": "^1.8.2",
58
+ "@docubook/mdx-content": "^3.4.3",
59
59
  "@docubook/runt": "^1.0.0",
60
60
  "@docubook/themes-colors": "^1.0.0",
61
61
  "@docubook/ui-react": "^1.0.0"
@@ -73,13 +73,11 @@
73
73
  "@types/node": "^22.0.0",
74
74
  "@types/react": "^19.0.0",
75
75
  "@types/react-dom": "^19.0.0",
76
- "autoprefixer": "^10.4.0",
77
76
  "bun-types": "^1.3.0",
78
77
  "eslint": "^10.3.0",
79
78
  "eslint-plugin-perfectionist": "^5.9.0",
80
79
  "eslint-plugin-react": "^7.37.5",
81
80
  "eslint-plugin-react-hooks": "^7.1.1",
82
- "postcss": "^8.4.0",
83
81
  "tailwindcss": "^4.3.0",
84
82
  "typescript": "^5.9.3",
85
83
  "typescript-eslint": "^8.59.2"
@@ -8,7 +8,7 @@ Flame produces **flat static HTML** — no server, no database, no runtime requi
8
8
  ## GitHub Pages
9
9
 
10
10
  ```bash
11
- npm run deploy
11
+ npm run deploy # or: bun run deploy / deno task deploy
12
12
  ```
13
13
 
14
14
  This builds the site, adds `.nojekyll`, and generates a GitHub Actions workflow on first run.
@@ -16,7 +16,7 @@ This builds the site, adds `.nojekyll`, and generates a GitHub Actions workflow
16
16
  ## Manual
17
17
 
18
18
  ```bash
19
- npm run build
19
+ npm run build # or: bun run build / deno task build
20
20
  ```
21
21
 
22
22
  Upload `.docu/dist/` to any of:
@@ -1,126 +0,0 @@
1
- /**
2
- * Build output summary: walks `dist` after a build, collects generated files
3
- * and their sizes, groups them by extension, and formats a scannable report
4
- * for CI logs. Runtime-neutral — uses only `node:fs/promises` and `node:path`
5
- * so it runs identically under Bun, Node, and Deno.
6
- */
7
-
8
- import { readdir, stat } from "node:fs/promises";
9
- import { join, relative, extname } from "node:path";
10
- import { existsSync } from "node:fs";
11
-
12
- export interface BuildOutputFile {
13
- path: string;
14
- size: number;
15
- }
16
-
17
- export interface BuildOutputType {
18
- ext: string;
19
- count: number;
20
- size: number;
21
- }
22
-
23
- export interface BuildOutput {
24
- files: BuildOutputFile[];
25
- byType: BuildOutputType[];
26
- totalFiles: number;
27
- totalSize: number;
28
- }
29
-
30
- const MAX_FILES_SHOWN = 10;
31
- const SEP = "─".repeat(60);
32
-
33
- export function formatSize(bytes: number): string {
34
- if (bytes < 1024) return `${bytes} B`;
35
- if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;
36
- return `${(bytes / (1024 * 1024)).toFixed(2)} MB`;
37
- }
38
-
39
- async function walkFiles(dir: string): Promise<BuildOutputFile[]> {
40
- const out: BuildOutputFile[] = [];
41
- const entries = await readdir(dir, { withFileTypes: true });
42
- for (const entry of entries) {
43
- const full = join(dir, entry.name);
44
- if (entry.isDirectory()) {
45
- out.push(...(await walkFiles(full)));
46
- } else if (entry.isFile()) {
47
- const s = await stat(full);
48
- out.push({ path: full, size: s.size });
49
- }
50
- }
51
- return out;
52
- }
53
-
54
- /** Collect build output metadata for `distDir`. Returns `null` if the dir is missing or empty. */
55
- export async function collectBuildOutput(distDir: string): Promise<BuildOutput | null> {
56
- if (!existsSync(distDir)) return null;
57
- const all = await walkFiles(distDir);
58
- if (all.length === 0) return null;
59
-
60
- const files = all
61
- .map((f) => ({ path: relative(distDir, f.path), size: f.size }))
62
- .sort((a, b) => (b.size !== a.size ? b.size - a.size : a.path.localeCompare(b.path)));
63
-
64
- const byExt = new Map<string, BuildOutputType>();
65
- for (const f of files) {
66
- const ext = extname(f.path) || "(none)";
67
- const entry = byExt.get(ext) ?? { ext, count: 0, size: 0 };
68
- entry.count++;
69
- entry.size += f.size;
70
- byExt.set(ext, entry);
71
- }
72
- const byType = [...byExt.values()].sort((a, b) =>
73
- b.size !== a.size ? b.size - a.size : b.count - a.count
74
- );
75
-
76
- return {
77
- files,
78
- byType,
79
- totalFiles: files.length,
80
- totalSize: files.reduce((sum, f) => sum + f.size, 0),
81
- };
82
- }
83
-
84
- /** Format `output` as a human-readable, color-free summary suitable for CI logs. */
85
- export function formatBuildSummary(output: BuildOutput): string {
86
- const lines: string[] = [];
87
- lines.push("📦 Build Output Summary:");
88
- lines.push(SEP);
89
-
90
- const shown = output.files.slice(0, MAX_FILES_SHOWN);
91
- const nameWidth = Math.min(Math.max(...shown.map((f) => f.path.length), 1), 50);
92
- for (const f of shown) {
93
- lines.push(` ${f.path.padEnd(nameWidth)} ${formatSize(f.size).padStart(10)}`);
94
- }
95
- const remaining = output.totalFiles - shown.length;
96
- if (remaining > 0) {
97
- lines.push(` ... and ${remaining} more file${remaining === 1 ? "" : "s"}`);
98
- }
99
-
100
- lines.push(SEP);
101
- lines.push("📊 Summary by Type:");
102
- const extWidth = Math.max(...output.byType.map((t) => t.ext.length), 1);
103
- for (const t of output.byType) {
104
- const plural = t.count === 1 ? "file" : "files";
105
- lines.push(
106
- ` ${t.ext.padEnd(extWidth)} ${String(t.count).padStart(3)} ${plural} ${formatSize(
107
- t.size
108
- ).padStart(10)}`
109
- );
110
- }
111
-
112
- lines.push(SEP);
113
- const totalPlural = output.totalFiles === 1 ? "file" : "files";
114
- lines.push(
115
- `📈 Total: ${output.totalFiles} ${totalPlural} ${formatSize(output.totalSize).padStart(10)}`
116
- );
117
- lines.push(SEP);
118
-
119
- return lines.join("\n");
120
- }
121
-
122
- /** Collect and format the build summary for `distDir`. Returns `null` when there is nothing to report. */
123
- export async function generateBuildSummary(distDir: string): Promise<string | null> {
124
- const output = await collectBuildOutput(distDir);
125
- return output ? formatBuildSummary(output) : null;
126
- }