core/loaders/chapter.loader.ts

core/loaders/chapter.loader.ts is a file in Bane's Lab Content. 104 lines of code and 19 definitions.

import { ATTRIBUTION_COPYRIGHT, ATTRIBUTION_WORK } from "#configuration/strings/chapter.strings";
import type {
    Attribution,
    ChapterShape,
    ChapterSource,
    PageSources,
    ShapeInput,
    ShapeRenderer,
} from "#types/chapter.types";
import { CREATIVE_COMMONS_LICENSE, METHODOLOGY_AUTHOR } from "@banes-lab/web/configuration/strings/page.strings.ts";
import {
    FOLDER_SEPARATOR,
    MARKDOWN_EXTENSION,
    REPOSITORY_SHAPE,
    WIKI_SHAPE,
} from "#configuration/constants/chapter.constants";
import { README_PAGES, REPOSITORY_PAGES, TEACHING_PAGES } from "#configuration/constants/readme.constants";
import { existsSync, readFileSync } from "node:fs";
import { payloadFileOf, readPagePayload } from "#core/loaders/payload.loader";
import type { PagePayload } from "#types/leak.types";
import { UTF8 } from "#configuration/constants/source.constants";
import { absolutePath } from "@ssot/paths";
import { readmeInputsOf } from "#core/loaders/readme.loader";
import { renderChapters } from "#core/renderers/chapter.renderer";
import { renderWiki } from "#core/renderers/wiki.renderer";

export const shapeOf = function shapeOf(value: string | null): ChapterShape | null {
    if (value === null || value === REPOSITORY_SHAPE) {
        return REPOSITORY_SHAPE;
    }
    return value === WIKI_SHAPE ? WIKI_SHAPE : null;
};

export const rendererFor = function rendererFor(shape: ChapterShape): ShapeRenderer {
    if (shape === WIKI_SHAPE) {
        return renderWiki;
    }
    return renderChapters;
};

const readTwin = function readTwin(file: string): string | null {
    return existsSync(file) ? readFileSync(file, UTF8) : null;
};

export const twinFilesOf = function twinFilesOf(payload: PagePayload): string[] {
    const pageTwin = absolutePath("builds.web", payload.page + MARKDOWN_EXTENSION);
    if (payload.tabs.length === 0) {
        return [pageTwin];
    }
    return payload.tabs.map((tab, index) =>
        index === 0
            ? pageTwin
            : absolutePath("builds.web", payload.page + FOLDER_SEPARATOR + tab.id + MARKDOWN_EXTENSION),
    );
};

export const chapterSourcesOf = function chapterSourcesOf(payload: PagePayload): ChapterSource[] | null {
    const files = twinFilesOf(payload);
    const sources: ChapterSource[] = [];
    for (const [index, file] of files.entries()) {
        const markdown = readTwin(file);
        if (markdown === null) {
            return null;
        }
        const tab = payload.tabs[index];
        sources.push(
            tab === undefined
                ? { first: true, label: payload.label, markdown, tab: payload.page }
                : { first: index === 0, label: tab.label, markdown, tab: tab.id },
        );
    }
    return sources;
};

export const pageSourcesOf = function pageSourcesOf(page: string): PageSources | null {
    const payload = readPagePayload(page);
    const sources = payload === null ? null : chapterSourcesOf(payload);
    return payload === null || sources === null ? null : { label: payload.label, page, sources };
};

export const pagesFor = function pagesFor(shape: ChapterShape): readonly string[] {
    return shape === WIKI_SHAPE ? TEACHING_PAGES : REPOSITORY_PAGES;
};

export const shapeInputOf = function shapeInputOf(shape: ChapterShape): ShapeInput | null {
    const pages = pagesFor(shape).map(pageSourcesOf);
    const present = pages.filter((page): page is PageSources => page !== null);
    if (present.length !== pages.length) {
        return null;
    }
    return { pages: present, readme: shape === REPOSITORY_SHAPE ? readmeInputsOf() : null };
};

export const attributionOf = function attributionOf(): Attribution {
    return {
        author: METHODOLOGY_AUTHOR,
        copyright: ATTRIBUTION_COPYRIGHT,
        coveredBy: CREATIVE_COMMONS_LICENSE.lead,
        licenseName: CREATIVE_COMMONS_LICENSE.name,
        licenseUrl: CREATIVE_COMMONS_LICENSE.href,
        work: ATTRIBUTION_WORK,
    };
};

export const surfaceFolder = function surfaceFolder(shape: ChapterShape): string {
    return shape === WIKI_SHAPE ? absolutePath("methodology.wiki") : absolutePath("methodology");
};

export const surfaceInputFiles = function surfaceInputFiles(shape: ChapterShape): string[] {
    const pages = shape === REPOSITORY_SHAPE ? [...pagesFor(shape), ...README_PAGES] : pagesFor(shape);
    return [...new Set(pages)].flatMap((page) => {
        const payload = readPagePayload(page);
        return [payloadFileOf(page), ...(payload === null ? [] : twinFilesOf(payload))];
    });
};