core/converters/site.converter.ts
core/converters/site.converter.ts is a file in Bane's Lab Build Scripts. 84 lines of code and 17 definitions.
import type { DiscoveredPage, DiscoveredRoute, Discovery } from "#types/site.types";
import type { PageDefinition, SiteSource } from "#types/page.types";
import type { TabsFor } from "#types/learning.types";
import { definitionOf } from "#core/selectors/page.selector";
import { mapSettled } from "#core/adapters/document.adapter";
import { tabsIn as tabRecordsIn } from "@banes-lab/content/core/selectors/payload.selector.ts";
import { textualize } from "#core/converters/payload.converter";
interface NamedTab {
readonly id: string;
readonly label: string;
}
const hasString = function hasString(value: object, key: string): boolean {
return key in value && typeof Reflect.get(value, key) === "string";
};
const isTab = function isTab(value: unknown): value is NamedTab {
return typeof value === "object" && value !== null && hasString(value, "id") && hasString(value, "label");
};
const tabsIn = function tabsIn(content: unknown): readonly NamedTab[] {
return tabRecordsIn(content).flatMap((tab) => (isTab(tab) ? [tab] : []));
};
const secondaryTabs = function secondaryTabs(content: unknown): readonly NamedTab[] {
return tabsIn(content).slice(1);
};
const hasSections = function hasSections(value: unknown): value is { readonly sections: readonly unknown[] } {
return typeof value === "object" && value !== null && "sections" in value && Array.isArray(value.sections);
};
const idsIn = function idsIn(holder: unknown): readonly string[] {
if (!hasSections(holder)) {
return [];
}
return holder.sections.flatMap((section) =>
typeof section === "object" && section !== null && hasString(section, "id")
? [String(Reflect.get(section, "id"))]
: [],
);
};
const sectionIdsOf = function sectionIdsOf(content: unknown, tab: string | null): readonly string[] {
if (tabRecordsIn(content).length === 0) {
return idsIn(content);
}
const tabs = tabsIn(content);
return idsIn(tab === null ? tabs[0] : tabs.find((entry) => entry.id === tab));
};
const tabRoutes = async function tabRoutes(loaded: SiteSource, definition: PageDefinition): Promise<DiscoveredRoute[]> {
return mapSettled(secondaryTabs(definition.content), (tab) => {
const path = loaded.links.tabLink(definition.id, tab.id);
return {
...loaded.renderer.headOf(definition.id, definition, path),
label: tab.label,
markdown: loaded.exportText(path, definition.id, sectionIdsOf(definition.content, tab.id)),
page: definition.id,
tab: tab.id,
};
});
};
export const tabsFromDiscovery = function tabsFromDiscovery(discovery: Discovery): TabsFor {
return (page) => tabRecordsIn(discovery.pages.find((entry) => entry.id === page)?.content ?? null);
};
export const discover = async function discover(loaded: SiteSource): Promise<Discovery> {
const pages = await mapSettled(loaded.ids, (page): DiscoveredPage => {
const definition = definitionOf(loaded, page);
const head = loaded.renderer.headOf(page, definition);
return {
...head,
content: textualize(definition.content, loaded.inline),
id: page,
label: definition.title,
markdown: loaded.exportText(head.path, page, sectionIdsOf(definition.content, null)),
page,
tab: null,
};
});
const tabs = await mapSettled(pages, async (page) => tabRoutes(loaded, definitionOf(loaded, page.id)));
const routes: DiscoveredRoute[] = pages.flatMap((page, index) => [page, ...(tabs[index] ?? [])]);
return {
author: loaded.author,
consent: loaded.consent,
name: loaded.name,
pages,
routes,
site: loaded.links.SITE_URL,
summary: loaded.summary,
};
};