@docubook/flame 2.0.0-beta.1 → 2.0.0-beta.3

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 (60) hide show
  1. package/.docu/lib/build.deno.js +6 -9
  2. package/.docu/lib/build.deno.js.map +1 -0
  3. package/.docu/lib/build.impl-Bz_p421t.js +424 -0
  4. package/.docu/lib/build.impl-Bz_p421t.js.map +1 -0
  5. package/.docu/lib/build.impl-CtPrlYAE.js +2 -0
  6. package/.docu/lib/build.node.js +6 -9
  7. package/.docu/lib/build.node.js.map +1 -0
  8. package/.docu/lib/clean.js +25 -25
  9. package/.docu/lib/clean.js.map +1 -0
  10. package/.docu/lib/deno-DmEaKggj.js +20 -0
  11. package/.docu/lib/deno-DmEaKggj.js.map +1 -0
  12. package/.docu/lib/deploy.deno.js +9 -9
  13. package/.docu/lib/deploy.deno.js.map +1 -0
  14. package/.docu/lib/deploy.node.js +8 -8
  15. package/.docu/lib/deploy.node.js.map +1 -0
  16. package/.docu/lib/deploy.shared-fk8eM-r4.js +295 -0
  17. package/.docu/lib/deploy.shared-fk8eM-r4.js.map +1 -0
  18. package/.docu/lib/html.shared-FwgbE1WG.js +2696 -0
  19. package/.docu/lib/html.shared-FwgbE1WG.js.map +1 -0
  20. package/.docu/lib/logger-CQyNTE6L.js +306 -0
  21. package/.docu/lib/logger-CQyNTE6L.js.map +1 -0
  22. package/.docu/lib/node-DPTySdwG.js +80 -0
  23. package/.docu/lib/node-DPTySdwG.js.map +1 -0
  24. package/.docu/lib/paths-Bl2cdp9E.js +76 -0
  25. package/.docu/lib/paths-Bl2cdp9E.js.map +1 -0
  26. package/.docu/lib/preview.deno.js +7 -11
  27. package/.docu/lib/preview.deno.js.map +1 -0
  28. package/.docu/lib/preview.impl-CnsbLmDA.js +77 -0
  29. package/.docu/lib/preview.impl-CnsbLmDA.js.map +1 -0
  30. package/.docu/lib/preview.node.js +7 -11
  31. package/.docu/lib/preview.node.js.map +1 -0
  32. package/.docu/lib/server.deno.js +7 -12
  33. package/.docu/lib/server.deno.js.map +1 -0
  34. package/.docu/lib/server.impl-CXTzYqbF.js +358 -0
  35. package/.docu/lib/server.impl-CXTzYqbF.js.map +1 -0
  36. package/.docu/lib/server.node.js +7 -12
  37. package/.docu/lib/server.node.js.map +1 -0
  38. package/.docu/lib/utils-DA17MyQG.js +167 -0
  39. package/.docu/lib/utils-DA17MyQG.js.map +1 -0
  40. package/.docu/node/build.impl.ts +76 -11
  41. package/.docu/node/build.ts +83 -9
  42. package/.docu/node/cache-key.ts +311 -0
  43. package/.docu/node/hydrate.node.ts +124 -177
  44. package/.docu/node/hydrate.ts +13 -14
  45. package/.docu/node/mdx.ts +14 -2
  46. package/.docu/node/paths.ts +27 -1
  47. package/.docu/node/types.ts +23 -5
  48. package/bin/cli.js +56 -18
  49. package/bin/compile-lib.mjs +30 -28
  50. package/package.json +10 -16
  51. package/.docu/lib/build.impl-3ZOQORN3.js +0 -12
  52. package/.docu/lib/chunk-4IQXHHPF.js +0 -62
  53. package/.docu/lib/chunk-6EOUQCRM.js +0 -301
  54. package/.docu/lib/chunk-6HFBJUMG.js +0 -434
  55. package/.docu/lib/chunk-EOK6KATZ.js +0 -191
  56. package/.docu/lib/chunk-FERG25YW.js +0 -470
  57. package/.docu/lib/chunk-MQRFIDS4.js +0 -92
  58. package/.docu/lib/chunk-U7M5SK76.js +0 -330
  59. package/.docu/lib/chunk-UISOJ4RW.js +0 -114
  60. package/.docu/lib/chunk-URBATJEC.js +0 -2720
@@ -7,37 +7,39 @@
7
7
  * The CLI routes non-Bun runtimes here (see `bin/cli.js`).
8
8
  */
9
9
 
10
- import { rmSync } from "node:fs";
11
- import { build, stop } from "esbuild";
10
+ import { build } from "vite";
12
11
 
13
- const ENTRIES = [
14
- "server.node.ts",
15
- "server.deno.ts",
16
- "build.node.ts",
17
- "build.deno.ts",
18
- "preview.node.ts",
19
- "preview.deno.ts",
20
- "deploy.node.ts",
21
- "deploy.deno.ts",
22
- "clean.ts",
12
+ const entries = [
13
+ "server.node",
14
+ "server.deno",
15
+ "build.node",
16
+ "build.deno",
17
+ "preview.node",
18
+ "preview.deno",
19
+ "deploy.node",
20
+ "deploy.deno",
21
+ "clean",
23
22
  ];
24
23
 
25
- rmSync(".docu/lib", { recursive: true, force: true });
24
+ const entry = Object.fromEntries(entries.map((name) => [name, `.docu/node/${name}.ts`]));
26
25
 
27
26
  await build({
28
- entryPoints: ENTRIES.map((entry) => `.docu/node/${entry}`),
29
- outdir: ".docu/lib",
30
- bundle: true,
31
- splitting: true,
32
- format: "esm",
33
- platform: "node",
34
- target: "node20",
35
- packages: "external",
36
- jsx: "automatic",
37
- logLevel: "info",
27
+ build: {
28
+ outDir: ".docu/lib",
29
+ emptyOutDir: true,
30
+ ssr: true,
31
+ target: "node20",
32
+ minify: false,
33
+ sourcemap: true,
34
+ lib: {
35
+ entry,
36
+ formats: ["es"],
37
+ fileName: (_format, entryName) => `${entryName}.js`,
38
+ },
39
+ rollupOptions: {
40
+ // Keep npm and runtime dependencies resolvable by the target runtime.
41
+ // Relative imports are bundled from the TypeScript source tree.
42
+ external: (id) => !id.startsWith(".") && !id.startsWith("/") && !id.startsWith("\0"),
43
+ },
44
+ },
38
45
  });
39
-
40
- // esbuild's service process keeps Deno's event loop alive after one-shot
41
- // build() calls — stop it explicitly so `flame` can invoke this script
42
- // under Deno. Harmless under Node.
43
- await stop();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docubook/flame",
3
- "version": "2.0.0-beta.1",
3
+ "version": "2.0.0-beta.3",
4
4
  "description": "A blazing-fast React + MDX framework powered by Bun, built for modern documentation experiences.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "engines": {
25
25
  "node": ">=20.11",
26
- "bun": ">=1.1.0"
26
+ "bun": ">=1.4.0"
27
27
  },
28
28
  "keywords": [
29
29
  "docubook",
@@ -50,16 +50,16 @@
50
50
  "@tailwindcss/typography": "0.5.16",
51
51
  "bun-plugin-tailwind": "^0.1.2",
52
52
  "daisyui": "^5.5.19",
53
- "esbuild": "^0.28.1",
54
53
  "lucide-react": "^1.14.0",
55
54
  "react": "^19.2.7",
56
55
  "react-dom": "^19.2.7",
57
56
  "unified": "^11.0.0",
57
+ "vite": "^8.2.1",
58
58
  "zod": "^4.4.3",
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"
59
+ "@docubook/core": "^2.0.0-beta.3",
60
+ "@docubook/markdown": "^2.0.0-beta.3",
61
+ "@docubook/themes-colors": "^2.0.0-beta.3",
62
+ "@docubook/ui-react": "^2.0.0-beta.3"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "@sentry/bun": "^10.0.0"
@@ -70,18 +70,12 @@
70
70
  }
71
71
  },
72
72
  "devDependencies": {
73
- "@eslint/js": "^10.0.1",
74
73
  "@types/node": "^22.0.0",
75
74
  "@types/react": "^19.0.0",
76
75
  "@types/react-dom": "^19.0.0",
77
- "bun-types": "^1.3.0",
78
- "eslint": "^10.3.0",
79
- "eslint-plugin-perfectionist": "^5.9.0",
80
- "eslint-plugin-react": "^7.37.5",
81
- "eslint-plugin-react-hooks": "^7.1.1",
76
+ "bun-types": "^1.4.0",
82
77
  "tailwindcss": "^4.3.0",
83
- "typescript": "^5.9.3",
84
- "typescript-eslint": "^8.59.2"
78
+ "typescript": "^7.0.2"
85
79
  },
86
80
  "scripts": {
87
81
  "dev": "bun .docu/node/server.ts",
@@ -91,6 +85,6 @@
91
85
  "deploy": "bun .docu/node/deploy.ts",
92
86
  "compile:lib": "node bin/compile-lib.mjs",
93
87
  "test": "vitest run",
94
- "lint": "eslint ."
88
+ "lint": "oxlint ."
95
89
  }
96
90
  }
@@ -1,12 +0,0 @@
1
- import {
2
- runBuild,
3
- runBuildCli
4
- } from "./chunk-FERG25YW.js";
5
- import "./chunk-URBATJEC.js";
6
- import "./chunk-EOK6KATZ.js";
7
- import "./chunk-6EOUQCRM.js";
8
- import "./chunk-4IQXHHPF.js";
9
- export {
10
- runBuild,
11
- runBuildCli
12
- };
@@ -1,62 +0,0 @@
1
- // .docu/node/paths.ts
2
- import { resolve, join } from "node:path";
3
- import { existsSync, readFileSync } from "node:fs";
4
- import { readdir, rm, unlink } from "node:fs/promises";
5
- var FRAMEWORK_ROOT = resolve(import.meta.dirname, "../..");
6
- var PROJECT_ROOT = process.cwd();
7
- var PAGES_DIR = join(FRAMEWORK_ROOT, ".docu/pages");
8
- var STYLES_DIR = join(FRAMEWORK_ROOT, ".docu/styles");
9
- var nodeDir = join(FRAMEWORK_ROOT, ".docu/node");
10
- var libDir = join(FRAMEWORK_ROOT, ".docu/lib");
11
- var LIB_DIR = existsSync(nodeDir) ? nodeDir : libDir;
12
- var DIST_DIR = join(PROJECT_ROOT, ".docu/dist");
13
- var ASSETS_DIR = join(DIST_DIR, "assets");
14
- var CACHE_FILE = join(PROJECT_ROOT, ".docu/build-cache.json");
15
- var DOCS_DIR = join(PROJECT_ROOT, "docs");
16
- var DOCS_ASSETS_DIR = join(PROJECT_ROOT, "docs/assets");
17
- var DOCU_CONFIG_PATH = join(PROJECT_ROOT, "docu.json");
18
- var _config = null;
19
- async function cleanOldBundles(preserve) {
20
- try {
21
- const files = await readdir(ASSETS_DIR);
22
- for (const file of files) {
23
- if (preserve?.has(file)) continue;
24
- if (file.startsWith("client.") || file.startsWith("client-")) {
25
- await unlink(join(ASSETS_DIR, file));
26
- }
27
- }
28
- } catch (err) {
29
- if (err.code !== "ENOENT") {
30
- console.error("Failed to clean old bundles:", err.message);
31
- }
32
- }
33
- try {
34
- await rm(join(ASSETS_DIR, "chunks"), { recursive: true, force: true });
35
- } catch (err) {
36
- if (err.code !== "ENOENT") {
37
- console.warn("[flame] Failed to clean chunks dir:", err.message);
38
- }
39
- }
40
- }
41
- function loadDocuConfig() {
42
- if (_config) return _config;
43
- if (!existsSync(DOCU_CONFIG_PATH)) {
44
- throw new Error(`docu.json not found at ${DOCU_CONFIG_PATH}`);
45
- }
46
- _config = JSON.parse(readFileSync(DOCU_CONFIG_PATH, "utf-8"));
47
- return _config;
48
- }
49
-
50
- export {
51
- FRAMEWORK_ROOT,
52
- PROJECT_ROOT,
53
- STYLES_DIR,
54
- LIB_DIR,
55
- DIST_DIR,
56
- ASSETS_DIR,
57
- CACHE_FILE,
58
- DOCS_DIR,
59
- DOCS_ASSETS_DIR,
60
- cleanOldBundles,
61
- loadDocuConfig
62
- };
@@ -1,301 +0,0 @@
1
- import {
2
- loadDocuConfig
3
- } from "./chunk-4IQXHHPF.js";
4
-
5
- // package.json
6
- var package_default = {
7
- name: "@docubook/flame",
8
- version: "2.0.0-beta.1",
9
- description: "A blazing-fast React + MDX framework powered by Bun, built for modern documentation experiences.",
10
- type: "module",
11
- bin: {
12
- flame: "./bin/cli.js"
13
- },
14
- files: [
15
- "bin",
16
- "template",
17
- "docu.schema.json",
18
- ".docu",
19
- "!.docu/__tests__",
20
- "!.docu/dist",
21
- "!.docu/build-cache.json",
22
- "README.md",
23
- "LICENSE"
24
- ],
25
- publishConfig: {
26
- registry: "https://registry.npmjs.org/",
27
- access: "public"
28
- },
29
- engines: {
30
- node: ">=20.11",
31
- bun: ">=1.1.0"
32
- },
33
- scripts: {
34
- dev: "bun .docu/node/server.ts",
35
- build: "NODE_ENV=production bun .docu/node/build.ts",
36
- clean: "bun .docu/node/clean.ts",
37
- preview: "bun .docu/node/preview.ts",
38
- deploy: "bun .docu/node/deploy.ts",
39
- "compile:lib": "node bin/compile-lib.mjs",
40
- test: "vitest run",
41
- lint: "eslint .",
42
- prepublishOnly: "bun .docu/node/clean.ts && eslint . && vitest run && node bin/compile-lib.mjs"
43
- },
44
- keywords: [
45
- "docubook",
46
- "documentation",
47
- "static-site",
48
- "daisyui",
49
- "bun",
50
- "docs framework",
51
- "react",
52
- "react-dom"
53
- ],
54
- homepage: "https://github.com/DocuBook/docubook/tree/main/packages/flame",
55
- repository: {
56
- type: "git",
57
- url: "git+https://github.com/DocuBook/docubook.git",
58
- directory: "packages/flame"
59
- },
60
- author: "wildan.nrs",
61
- "author-url": "https://wildan.dev",
62
- license: "MIT",
63
- dependencies: {
64
- "@docubook/core": "workspace:^",
65
- "@docubook/markdown": "workspace:^",
66
- "@docubook/themes-colors": "workspace:^",
67
- "@docubook/ui-react": "workspace:^",
68
- "@mdx-js/react": "^3.0.1",
69
- "@tailwindcss/cli": "4.3.0",
70
- "@tailwindcss/typography": "0.5.16",
71
- "bun-plugin-tailwind": "^0.1.2",
72
- daisyui: "^5.5.19",
73
- esbuild: "^0.28.1",
74
- "lucide-react": "^1.14.0",
75
- react: "^19.2.7",
76
- "react-dom": "^19.2.7",
77
- unified: "^11.0.0",
78
- zod: "^4.4.3"
79
- },
80
- peerDependencies: {
81
- "@sentry/bun": "^10.0.0"
82
- },
83
- peerDependenciesMeta: {
84
- "@sentry/bun": {
85
- optional: true
86
- }
87
- },
88
- devDependencies: {
89
- "@eslint/js": "^10.0.1",
90
- "@types/node": "^22.0.0",
91
- "@types/react": "^19.0.0",
92
- "@types/react-dom": "^19.0.0",
93
- "bun-types": "^1.3.0",
94
- eslint: "^10.3.0",
95
- "eslint-plugin-perfectionist": "^5.9.0",
96
- "eslint-plugin-react": "^7.37.5",
97
- "eslint-plugin-react-hooks": "^7.1.1",
98
- tailwindcss: "^4.3.0",
99
- typescript: "^5.9.3",
100
- "typescript-eslint": "^8.59.2"
101
- }
102
- };
103
-
104
- // .docu/node/logger.ts
105
- var docuConfig = loadDocuConfig();
106
- var isCI = !!(process.env.CI || process.env.NO_COLOR || !process.stdout.isTTY);
107
- var LOG_FORMAT = process.env.LOG_FORMAT || "pretty";
108
- var isJSON = LOG_FORMAT === "json";
109
- var LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };
110
- var currentLevel = LEVELS[process.env.LOG_LEVEL || "info"] ?? LEVELS.info;
111
- function shouldLog(level) {
112
- return LEVELS[level] >= currentLevel;
113
- }
114
- function jsonLog(level, msg, meta) {
115
- if (!shouldLog(level)) return;
116
- const entry = { ts: (/* @__PURE__ */ new Date()).toISOString(), ...meta, level, msg };
117
- const out = level === "error" ? console.error : level === "warn" ? console.warn : console.log;
118
- out(JSON.stringify(entry));
119
- }
120
- function guard(level, msg, meta) {
121
- if (isJSON) {
122
- jsonLog(level, msg, meta);
123
- return true;
124
- }
125
- return !shouldLog(level);
126
- }
127
- var c = isCI || isJSON ? {
128
- reset: "",
129
- bold: "",
130
- dim: "",
131
- green: "",
132
- cyan: "",
133
- magenta: "",
134
- yellow: "",
135
- red: "",
136
- white: "",
137
- gray: ""
138
- } : {
139
- reset: "\x1B[0m",
140
- bold: "\x1B[1m",
141
- dim: "\x1B[2m",
142
- green: "\x1B[32m",
143
- cyan: "\x1B[36m",
144
- magenta: "\x1B[35m",
145
- yellow: "\x1B[33m",
146
- red: "\x1B[31m",
147
- white: "\x1B[37m",
148
- gray: "\x1B[90m"
149
- };
150
- var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
151
- var Spinner = class {
152
- frame = 0;
153
- message = "";
154
- timer = null;
155
- info(finalMsg) {
156
- if (this.timer) clearInterval(this.timer);
157
- this.timer = null;
158
- if (isCI) {
159
- console.log(`\u2139 ${finalMsg}`);
160
- } else {
161
- process.stdout.write(`\r\x1B[K${c.cyan}\u2139${c.reset} ${finalMsg}
162
- `);
163
- process.stdout.write("\x1B[?25h");
164
- }
165
- }
166
- start(msg) {
167
- this.message = msg;
168
- if (isCI) {
169
- console.log(`\u2026 ${msg}`);
170
- return;
171
- }
172
- this.frame = 0;
173
- process.stdout.write("\x1B[?25l");
174
- this.render();
175
- this.timer = setInterval(() => this.render(), 80);
176
- }
177
- stop(finalMsg) {
178
- if (this.timer) clearInterval(this.timer);
179
- this.timer = null;
180
- if (isCI) {
181
- console.log(`\u2713 ${finalMsg}`);
182
- return;
183
- }
184
- process.stdout.write(`\r\x1B[K${c.green}\u2713${c.reset} ${finalMsg}
185
- `);
186
- process.stdout.write("\x1B[?25h");
187
- }
188
- render() {
189
- const f = SPINNER_FRAMES[this.frame % SPINNER_FRAMES.length];
190
- process.stdout.write(`\r${c.cyan}${f}${c.reset} ${this.message}`);
191
- this.frame++;
192
- }
193
- };
194
- var MAX_ROUTE_LINES = 5;
195
- var routeLineCount = 0;
196
- var routeTruncated = false;
197
- function printRouteTree(routes, prefix = "", isRoot = true) {
198
- for (let i = 0; i < routes.length; i++) {
199
- if (routeTruncated) return;
200
- if (routeLineCount >= MAX_ROUTE_LINES) {
201
- routeTruncated = true;
202
- process.stdout.write(`${prefix}${c.dim}...${c.reset}
203
- `);
204
- return;
205
- }
206
- const route = routes[i];
207
- const last = i === routes.length - 1;
208
- const connector = isRoot ? "" : last ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
209
- const childPrefix = isRoot ? "" : last ? " " : "\u2502 ";
210
- const path = route.noLink ? `${c.dim}${route.href}${c.reset}` : `${c.white}${route.href}${c.reset}`;
211
- const label = route.noLink ? `${c.gray}(group)${c.reset}` : "";
212
- process.stdout.write(`${prefix}${connector}${path} ${label}
213
- `);
214
- routeLineCount++;
215
- if (route.items?.length) {
216
- printRouteTree(route.items, prefix + childPrefix, false);
217
- }
218
- }
219
- }
220
- var logger = {
221
- spinner: new Spinner(),
222
- buildStart() {
223
- if (guard("info", "build_start", { package: "@docubook/flame", version: package_default.version })) return;
224
- console.log(
225
- `
226
- ${c.bold}${c.cyan} \u{1F525} DocuBook Flame${c.reset} ${c.dim}v${package_default.version}${c.reset}
227
- `
228
- );
229
- },
230
- bundleStart() {
231
- if (guard("info", "bundle_start")) return;
232
- this.spinner.start("Building client bundle...");
233
- },
234
- bundleDone(ms) {
235
- if (guard("info", "bundle_done", { duration_ms: ms })) return;
236
- this.spinner.stop(`Client bundle compiled ${c.dim}(${ms}ms)${c.reset}`);
237
- },
238
- indexStart() {
239
- if (guard("info", "index_start")) return;
240
- this.spinner.start("Generating search index...");
241
- },
242
- indexDone(records, ms, skipped = false) {
243
- if (guard("info", "index_done", { records, duration_ms: ms, skipped })) return;
244
- this.spinner.stop(
245
- skipped ? `Search index cached ${c.dim}(${ms}ms)${c.reset}` : `Search index generated ${c.dim}(${records} records, ${ms}ms)${c.reset}`
246
- );
247
- },
248
- routes() {
249
- if (guard("debug", "routes")) return;
250
- const routes = docuConfig.routes;
251
- if (!routes?.length) return;
252
- console.log(`
253
- ${c.bold} Routes${c.reset} ${c.dim}(${countRoutes(routes)} pages)${c.reset}
254
- `);
255
- routeLineCount = 0;
256
- routeTruncated = false;
257
- printRouteTree(routes, " ");
258
- },
259
- ready(port, hmr = false) {
260
- if (guard("info", "server_ready", { port, hmr })) return;
261
- console.log(
262
- `
263
- ${c.green}${c.bold} \u2713 Ready${c.reset} in ${c.bold}http://localhost:${port}/docs/${c.reset}`
264
- );
265
- if (hmr) console.log(`${c.dim} HMR enabled \u2014 watching docs/ for changes${c.reset}`);
266
- console.log("");
267
- },
268
- request(method, pathname, status, duration_ms) {
269
- if (guard("info", "http_request", { method, path: pathname, status, duration_ms })) return;
270
- const color = status >= 500 ? c.red : status >= 400 ? c.gray : c.green;
271
- const ts = (/* @__PURE__ */ new Date()).toLocaleTimeString();
272
- const dur = duration_ms != null ? ` ${c.dim}${duration_ms}ms${c.reset}` : "";
273
- console.log(
274
- `${c.dim} ${ts}${c.reset} ${method} ${pathname} ${color}${status}${c.reset}${dur}`
275
- );
276
- },
277
- debug(msg, meta) {
278
- if (guard("debug", msg, meta)) return;
279
- console.log(`${c.gray} [debug] ${msg}${c.reset}`);
280
- },
281
- warn(msg, meta) {
282
- if (guard("warn", msg, meta)) return;
283
- console.warn(`${c.yellow} \u26A0 ${msg}${c.reset}`);
284
- },
285
- error(msg, meta) {
286
- if (guard("error", msg, meta)) return;
287
- console.error(`${c.red} \u2716 ${msg}${c.reset}`);
288
- }
289
- };
290
- function countRoutes(routes) {
291
- let count = 0;
292
- for (const r of routes) {
293
- if (!r.noLink) count++;
294
- if (r.items) count += countRoutes(r.items);
295
- }
296
- return count;
297
- }
298
-
299
- export {
300
- logger
301
- };