# core/loaders/chapter.loader.ts

> 89 lines of code and 15 definitions.

Tree: Build tree
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/build#file-build-core-loaders-chapter-loader-ts
Source text: https://banes-lab.com/assets/sources/source.1589182e2bb791fbee3489e3717441cf5bf7ef96e9cb7850d0f6bc6b702aea0f.generated.txt

## Definitions

- `pagesFor` (lexical_declaration, line 72, exported)
- `shapeInputOf` (lexical_declaration, line 76, exported)
- `shapeOf` (lexical_declaration, line 28, exported)
- `rendererFor` (lexical_declaration, line 35, exported)
- `readTwin` (lexical_declaration, line 42)
- `chapterSourcesOf` (lexical_declaration, line 46, exported)
- `file` (lexical_declaration, line 49, exported)
- `markdown` (lexical_declaration, line 60, exported)
- `pageSourcesOf` (lexical_declaration, line 66, exported)
- `payload` (lexical_declaration, line 67, exported)
- `sources` (lexical_declaration, line 68, exported)
- `pages` (lexical_declaration, line 77, exported)
- `present` (lexical_declaration, line 78, exported)
- `attributionOf` (lexical_declaration, line 85, exported)
- `surfaceFolder` (lexical_declaration, line 96, exported)

## Uses

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

## Used by

- [core/coordinators/chapter.coordinator.ts](https://banes-lab.com/source/build/core/coordinators/chapter.coordinator.ts.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 {
    FOLDER_SEPARATOR,
    MARKDOWN_EXTENSION,
    REPOSITORY_SHAPE,
    WIKI_SHAPE,
} from "#configuration/constants/chapter.constants";
import { REPOSITORY_PAGES, TEACHING_PAGES } from "#configuration/constants/readme.constants";
import { existsSync, readFileSync } from "node:fs";
import { CREATIVE_COMMONS_LICENSE } from "@banes-lab/web/configuration/strings/page.strings.ts";
import { METHODOLOGY_AUTHOR } from "@banes-lab/web/configuration/strings/methodology.strings.ts";
import type { PagePayload } from "#types/leak.types";
import { UTF8 } from "#configuration/constants/source.constants";
import { absolutePath } from "@ssot/paths";
import { readPagePayload } from "#core/loaders/payload.loader";
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 chapterSourcesOf = function chapterSourcesOf(payload: PagePayload): ChapterSource[] | null {
    const sources: ChapterSource[] = [];
    for (const [index, tab] of payload.tabs.entries()) {
        const file =
            index === 0
                ? absolutePath("builds.web", payload.page + MARKDOWN_EXTENSION)
                : absolutePath("builds.web", payload.page + FOLDER_SEPARATOR + tab.id + MARKDOWN_EXTENSION);
        const markdown = readTwin(file);
        if (markdown === null) {
            return null;
        }
        sources.push({ first: index === 0, label: tab.label, markdown, tab: tab.id });
    }
    if (sources.length === 0) {
        const markdown = readTwin(absolutePath("builds.web", payload.page + MARKDOWN_EXTENSION));
        return markdown === null ? null : [{ first: true, label: payload.label, markdown, tab: payload.page }];
    }
    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");
};
```
