# core/loaders/chapter.loader.ts

> 104 lines of code and 19 definitions.

Tree: Bane's Lab Content
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/content#file-content-core-loaders-chapter-loader-ts
Source text: https://banes-lab.com/source/content/core/loaders/chapter.loader.ts.txt

Listed in [core/loaders](https://banes-lab.com/api/source/content/core/loaders.md), before [core/loaders/coordination.loader.ts](https://banes-lab.com/source/content/core/loaders/coordination.loader.ts.md).

## Definitions

- `twinFilesOf` (lexical_declaration, line 45, exported)
- `pagesFor` (lexical_declaration, line 81, exported)
- `surfaceInputFiles` (lexical_declaration, line 109, exported)
- `shapeInputOf` (lexical_declaration, line 85, exported)
- `shapeOf` (lexical_declaration, line 27, exported)
- `rendererFor` (lexical_declaration, line 34, exported)
- `readTwin` (lexical_declaration, line 41)
- `pageTwin` (lexical_declaration, line 46, exported)
- `chapterSourcesOf` (lexical_declaration, line 57, exported)
- `files` (lexical_declaration, line 58, exported)
- `markdown` (lexical_declaration, line 61, exported)
- `tab` (lexical_declaration, line 65, exported)
- `pageSourcesOf` (lexical_declaration, line 75, exported)
- `sources` (lexical_declaration, line 77, exported)
- `present` (lexical_declaration, line 87, exported)
- `attributionOf` (lexical_declaration, line 94, exported)
- `surfaceFolder` (lexical_declaration, line 105, exported)
- `pages` (lexical_declaration, line 110, exported)
- `payload` (lexical_declaration, line 112, exported)

## Contained in

- [core/loaders](https://banes-lab.com/anatomy/content/folder-content-core-loaders.md)

## Uses

- [core/loaders/payload.loader.ts](https://banes-lab.com/source/content/core/loaders/payload.loader.ts.md)
- [core/loaders/readme.loader.ts](https://banes-lab.com/source/content/core/loaders/readme.loader.ts.md)

## Used by

- [core/coordinators/chapter.coordinator.ts](https://banes-lab.com/source/content/core/coordinators/chapter.coordinator.ts.md)

## Linked from

- [core/coordinators](https://banes-lab.com/anatomy/content/folder-content-core-coordinators.md)
- [core/loaders](https://banes-lab.com/anatomy/content/folder-content-core-loaders.md)

## Source

```typescript
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))];
    });
};
```
