mdzilla 0.0.3 → 0.0.5
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/README.md +3 -1
- package/dist/_chunks/exporter.mjs +43 -5
- package/dist/_chunks/server.mjs +1882 -0
- package/dist/cli/main.mjs +25 -4
- package/dist/index.d.mts +3 -2
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -12,7 +12,9 @@ Markdown browser for humans and agents.
|
|
|
12
12
|
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
|
-
> Browse docs from local directories, GitHub repos, and remote websites — all from your terminal.
|
|
15
|
+
> Browse docs from local directories, GitHub repos, and remote websites — all from your terminal.
|
|
16
|
+
|
|
17
|
+
Built with [md4x](https://github.com/unjs/md4x), [mdream](https://github.com/harlan-zw/mdream), [giget](https://github.com/unjs/giget) and [speed-highlight](https://github.com/speed-highlight/core), [nitro](https://v3.nitro.build/), [h3](https://h3.dev/), [srvx](https://srvx.h3.dev/) and [vite](https://vite.dev/).
|
|
16
18
|
|
|
17
19
|
Supports any website with [`/llms.txt`](https://llmstxt.org/) or markdown content negotiation.
|
|
18
20
|
|
|
@@ -279,6 +279,7 @@ async function _scanNav(dirPath, parentPath, options) {
|
|
|
279
279
|
if (draft && !options.drafts) continue;
|
|
280
280
|
const meta = applyNavigationOverride(parseMeta(await readFile(fullPath, "utf8")));
|
|
281
281
|
if (meta.navigation === false) continue;
|
|
282
|
+
const resolvedOrder = typeof meta.order === "number" ? meta.order : order;
|
|
282
283
|
const resolvedSlug = slug === "index" ? "" : slug;
|
|
283
284
|
const title = meta.title || humanizeSlug(slug) || "index";
|
|
284
285
|
const entryPath = resolvedSlug === "" ? parentPath === "/" ? "/" : parentPath : parentPath === "/" ? `/${resolvedSlug}` : `${parentPath}/${resolvedSlug}`;
|
|
@@ -287,7 +288,7 @@ async function _scanNav(dirPath, parentPath, options) {
|
|
|
287
288
|
slug: resolvedSlug,
|
|
288
289
|
path: entryPath,
|
|
289
290
|
title,
|
|
290
|
-
order,
|
|
291
|
+
order: resolvedOrder,
|
|
291
292
|
...meta.icon ? { icon: meta.icon } : {},
|
|
292
293
|
...meta.description ? { description: meta.description } : {},
|
|
293
294
|
...draft ? { draft: true } : {},
|
|
@@ -308,8 +309,10 @@ var DocsSourceFS = class extends DocsSource {
|
|
|
308
309
|
this.dir = dir;
|
|
309
310
|
}
|
|
310
311
|
async load() {
|
|
312
|
+
const tree = await scanNav(this.dir);
|
|
313
|
+
await applyNavManifest(tree, this.dir);
|
|
311
314
|
return {
|
|
312
|
-
tree
|
|
315
|
+
tree,
|
|
313
316
|
fileMap: await buildFileMap("/", this.dir)
|
|
314
317
|
};
|
|
315
318
|
}
|
|
@@ -341,6 +344,30 @@ async function buildFileMap(parentPath, dirPath) {
|
|
|
341
344
|
}
|
|
342
345
|
return map;
|
|
343
346
|
}
|
|
347
|
+
/**
|
|
348
|
+
* Read `_navigation.json` manifest (exported by mdzilla) and apply its
|
|
349
|
+
* ordering to the scanned nav tree. Only reorders; does not add/remove entries.
|
|
350
|
+
*/
|
|
351
|
+
async function applyNavManifest(tree, dir) {
|
|
352
|
+
let manifest;
|
|
353
|
+
try {
|
|
354
|
+
manifest = JSON.parse(await readFile(join(dir, "_navigation.json"), "utf8"));
|
|
355
|
+
} catch {
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
reorderTree(tree, manifest);
|
|
359
|
+
}
|
|
360
|
+
/** Recursively reorder tree entries to match manifest ordering. */
|
|
361
|
+
function reorderTree(entries, manifest) {
|
|
362
|
+
const pathIndex = new Map(manifest.map((m, i) => [m.path, i]));
|
|
363
|
+
entries.sort((a, b) => {
|
|
364
|
+
return (pathIndex.get(a.path) ?? Infinity) - (pathIndex.get(b.path) ?? Infinity);
|
|
365
|
+
});
|
|
366
|
+
for (const entry of entries) if (entry.children?.length) {
|
|
367
|
+
const manifestEntry = manifest.find((m) => m.path === entry.path);
|
|
368
|
+
if (manifestEntry?.children) reorderTree(entry.children, manifestEntry.children);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
344
371
|
//#endregion
|
|
345
372
|
//#region src/docs/sources/git.ts
|
|
346
373
|
var DocsSourceGit = class extends DocsSource {
|
|
@@ -768,8 +795,9 @@ const IGNORED_PATHS = new Set(["/llms.txt", "/llms-full.txt"]);
|
|
|
768
795
|
/**
|
|
769
796
|
* Export documentation entries to a local filesystem directory as flat `.md` files.
|
|
770
797
|
*
|
|
771
|
-
* Each entry is written to `<dir>/<path>.md
|
|
772
|
-
*
|
|
798
|
+
* Each entry is written to `<dir>/<path>.md` (or `<dir>/<path>/index.md` for directory
|
|
799
|
+
* index pages). Navigation order is preserved via `order` frontmatter in pages and
|
|
800
|
+
* `.navigation.yml` files in directories.
|
|
773
801
|
*
|
|
774
802
|
* A `README.md` table of contents is generated at the root of the output directory.
|
|
775
803
|
*/
|
|
@@ -777,13 +805,15 @@ async function exportDocsToFS(manager, dir, options = {}) {
|
|
|
777
805
|
const rootEntry = manager.flat.find((f) => f.entry.path === "/");
|
|
778
806
|
const tocLines = [`# ${options.title ?? rootEntry?.entry.title ?? "Table of Contents"}`, ""];
|
|
779
807
|
const writtenFiles = /* @__PURE__ */ new Set();
|
|
808
|
+
const dirPaths = /* @__PURE__ */ new Set();
|
|
809
|
+
collectDirPaths(manager.tree, dirPaths);
|
|
780
810
|
for (const flat of manager.flat) {
|
|
781
811
|
if (options.filter ? !options.filter(flat) : flat.entry.page === false) continue;
|
|
782
812
|
if (IGNORED_PATHS.has(flat.entry.path)) continue;
|
|
783
813
|
let content = await manager.getContent(flat);
|
|
784
814
|
if (content === void 0) continue;
|
|
785
815
|
const cleanContent = options.plainText ? renderToText(content) : renderToMarkdown(content);
|
|
786
|
-
const filePath = flat.entry.path === "/" ? "/index.md" : flat.entry.path.endsWith(".md") ? flat.entry.path : `${flat.entry.path}.md`;
|
|
816
|
+
const filePath = flat.entry.path === "/" || dirPaths.has(flat.entry.path) ? flat.entry.path === "/" ? "/index.md" : `${flat.entry.path}/index.md` : flat.entry.path.endsWith(".md") ? flat.entry.path : `${flat.entry.path}.md`;
|
|
787
817
|
const dest = join(dir, filePath);
|
|
788
818
|
await mkdir(dirname(dest), { recursive: true });
|
|
789
819
|
await writeFile(dest, cleanContent, "utf8");
|
|
@@ -795,6 +825,14 @@ async function exportDocsToFS(manager, dir, options = {}) {
|
|
|
795
825
|
let tocFile = options.tocFile ?? "README.md";
|
|
796
826
|
if (writtenFiles.has(tocFile)) tocFile = `_${tocFile}`;
|
|
797
827
|
await writeFile(join(dir, tocFile), tocLines.join("\n") + "\n", "utf8");
|
|
828
|
+
await writeFile(join(dir, "_navigation.json"), JSON.stringify(manager.tree, null, 2) + "\n", "utf8");
|
|
829
|
+
}
|
|
830
|
+
/** Collect all paths that are directories (have children in the tree). */
|
|
831
|
+
function collectDirPaths(entries, set) {
|
|
832
|
+
for (const entry of entries) if (entry.children?.length) {
|
|
833
|
+
set.add(entry.path);
|
|
834
|
+
collectDirPaths(entry.children, set);
|
|
835
|
+
}
|
|
798
836
|
}
|
|
799
837
|
//#endregion
|
|
800
838
|
export { DocsSourceFS as a, DocsSourceGit as i, DocsSourceNpm as n, DocsSource as o, DocsSourceHTTP as r, DocsManager as s, exportDocsToFS as t };
|