2025-09-05 14:59:21 +08:00

97 lines
3.0 KiB
JavaScript

import { generateTitle } from "../transformers/path-meta.js";
import { useRuntimeConfig } from "#imports";
export function createNav(contents, configs) {
const { navigation } = useRuntimeConfig().public.content;
if (navigation === false) {
return [];
}
const pickNavigationFields = (content) => ({
...pick(["title", ...navigation.fields])(content),
...isObject(content?.navigation) ? content.navigation : {}
});
const nav = contents.sort((a, b) => a._path.localeCompare(b._path)).reduce((nav2, content) => {
const parts = content._path.substring(1).split("/");
const idParts = content._id.split(":").slice(1);
const isIndex = !!idParts[idParts.length - 1]?.match(/([1-9][0-9]*\.)?index.md/g);
const getNavItem = (content2) => ({
title: content2.title,
_path: content2._path,
_file: content2._file,
children: [],
...pickNavigationFields(content2),
...content2._draft ? { _draft: true } : {}
});
const navItem = getNavItem(content);
if (isIndex) {
const dirConfig = configs[navItem._path];
if (typeof dirConfig?.navigation !== "undefined" && !dirConfig?.navigation) {
return nav2;
}
if (content._path !== "/") {
const indexItem = getNavItem(content);
navItem.children.push(indexItem);
}
if (dirConfig) {
Object.assign(
navItem,
pickNavigationFields(dirConfig)
);
}
}
if (parts.length === 1) {
nav2.push(navItem);
return nav2;
}
const siblings = parts.slice(0, -1).reduce((nodes, part, i) => {
const currentPathPart = "/" + parts.slice(0, i + 1).join("/");
const conf = configs[currentPathPart];
if (typeof conf?.navigation !== "undefined" && !conf.navigation) {
return [];
}
let parent = nodes.find((n) => n._path === currentPathPart);
if (!parent) {
parent = {
title: generateTitle(part),
_path: currentPathPart,
_file: content._file,
children: [],
...conf && pickNavigationFields(conf)
};
nodes.push(parent);
}
return parent.children;
}, nav2);
siblings.push(navItem);
return nav2;
}, []);
return sortAndClear(nav);
}
const collator = new Intl.Collator(void 0, { numeric: true, sensitivity: "base" });
function sortAndClear(nav) {
nav.forEach((item) => {
item._file = item._file.split(".").slice(0, -1).join(".");
});
const sorted = nav.sort((a, b) => collator.compare(a._file, b._file));
for (const item of sorted) {
if (item.children?.length) {
sortAndClear(item.children);
} else {
delete item.children;
}
delete item._file;
}
return nav;
}
function pick(keys) {
return (obj) => {
obj = obj || {};
if (keys && keys.length) {
return keys.filter((key) => typeof obj[key] !== "undefined").reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {});
}
return obj;
};
}
function isObject(obj) {
return Object.prototype.toString.call(obj) === "[object Object]";
}