97 lines
3.0 KiB
JavaScript
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]";
|
|
}
|