core/formatters/index.formatter.ts

core/formatters/index.formatter.ts is a file in GovLab Docs. 168 lines of code and 40 definitions.

import type { ByGroup, PackageInfo } from "#types/index.types";
import {
    GROUP_ROLES,
    INDEX_HEADINGS,
    INDEX_TABLES,
    INDEX_TEXT,
    composeLine,
    composesPeers,
    concernRow,
    groupRow,
    indexSummary,
    inventoryRow,
    reproduceNote,
    standaloneLine,
} from "#configuration/strings/index.strings";
import { ENTRYPOINT_FILES } from "#configuration/constants/invocation.constants";
import { relativePath } from "@ssot/paths";

const MIN_COMPOSER_DEPS = 2;
const PURPOSE_TREE_MAX = 80;
const CONCERN_MAX = 110;
const LINE_BREAK = "\n";
const BLOCK_BREAK = "\n\n";
const FENCE = "```";
const SENTENCE_END = ".";
const PEER_JOIN = "` + `";
const NO_SIBLINGS = "—";
const BRANCH = "├── ";
const LAST_BRANCH = "└── ";
const PIPE_INDENT = "│   ";
const BLANK_INDENT = "    ";
const FOLDER_MARK = "/";
const PURPOSE_JOIN = " — ";

export const roleOf = function roleOf(group: string): string {
    if (group === relativePath("app.root")) {
        return GROUP_ROLES.application;
    }
    return group === relativePath("govlab.root") ? GROUP_ROLES.tooling : GROUP_ROLES.unclassified;
};

const branchAt = function branchAt(isLast: boolean): string {
    return isLast ? LAST_BRANCH : BRANCH;
};

const firstSentence = function firstSentence(text: string): string {
    return text.split(SENTENCE_END)[0] ?? "";
};

const sortedGroups = function sortedGroups(byGroup: ByGroup): string[] {
    return Object.keys(byGroup).toSorted((left, right) => left.localeCompare(right));
};

const treeLine = function treeLine(prefix: string, pkg: PackageInfo, isLast: boolean): string {
    const tag = pkg.siblingDeps.length >= MIN_COMPOSER_DEPS ? composesPeers(pkg.siblingDeps.length) : "";
    const purpose =
        pkg.purpose === null ? "" : `${PURPOSE_JOIN}${firstSentence(pkg.purpose).slice(0, PURPOSE_TREE_MAX)}`;
    return `${prefix}${branchAt(isLast)}${pkg.slug}${tag}${purpose}`;
};

const groupTree = function groupTree(group: string, packages: readonly PackageInfo[], isLastGroup: boolean): string[] {
    const prefix = isLastGroup ? BLANK_INDENT : PIPE_INDENT;
    return [
        `${branchAt(isLastGroup)}${group}${FOLDER_MARK}`,
        ...packages.map((pkg, index) => treeLine(prefix, pkg, index === packages.length - 1)),
    ];
};

const renderTree = function renderTree(byGroup: ByGroup): string {
    const groups = sortedGroups(byGroup);
    return [
        INDEX_TEXT.treeRoot,
        ...groups.flatMap((group, index) => groupTree(group, byGroup[group] ?? [], index === groups.length - 1)),
    ].join(LINE_BREAK);
};

const dependencyBlock = function dependencyBlock(pkg: PackageInfo): string {
    const lines = pkg.siblingDeps.map((dep, index) => `${branchAt(index === pkg.siblingDeps.length - 1)}${dep}`);
    return [pkg.name, ...lines].join(LINE_BREAK);
};

const renderDependencies = function renderDependencies(packages: readonly PackageInfo[]): string {
    const composers = packages.filter((pkg) => pkg.siblingDeps.length > 0);
    return composers.length === 0 ? INDEX_TEXT.noComposers : composers.map(dependencyBlock).join(BLOCK_BREAK);
};

const renderInventory = function renderInventory(packages: readonly PackageInfo[]): string {
    const rows = packages.map((pkg) =>
        inventoryRow({
            exports: pkg.barrelExports,
            group: pkg.group,
            loc: pkg.sourceLoc,
            name: pkg.name,
            siblings: pkg.siblingDeps.length === 0 ? NO_SIBLINGS : String(pkg.siblingDeps.length),
            sources: pkg.sourceFiles,
        }),
    );
    return [...INDEX_TABLES.inventory, ...rows].join(LINE_BREAK);
};

const concernOf = function concernOf(pkg: PackageInfo): string {
    return (pkg.purpose === null ? pkg.description : firstSentence(pkg.purpose)).slice(0, CONCERN_MAX);
};

const renderConcerns = function renderConcerns(packages: readonly PackageInfo[]): string {
    return [...INDEX_TABLES.concerns, ...packages.map((pkg) => concernRow(concernOf(pkg), pkg.name))].join(LINE_BREAK);
};

const renderGroups = function renderGroups(byGroup: ByGroup): string {
    const rows = sortedGroups(byGroup).map((group) => groupRow(group, roleOf(group), (byGroup[group] ?? []).length));
    return [...INDEX_TABLES.groups, ...rows].join(LINE_BREAK);
};

const summaryOf = function summaryOf(packages: readonly PackageInfo[]): string {
    return indexSummary({
        composers: packages.filter((pkg) => pkg.siblingDeps.length >= MIN_COMPOSER_DEPS).length,
        exports: packages.reduce((sum, pkg) => sum + pkg.barrelExports, 0),
        leaves: packages.filter((pkg) => pkg.siblingDeps.length === 0).length,
        loc: packages.reduce((sum, pkg) => sum + pkg.sourceLoc, 0),
        packages: packages.length,
    });
};

const compositionLines = function compositionLines(packages: readonly PackageInfo[]): string[] {
    const composers = packages.filter((pkg) => pkg.siblingDeps.length >= MIN_COMPOSER_DEPS);
    const leaves = packages.filter((pkg) => pkg.siblingDeps.length === 0);
    return [
        INDEX_HEADINGS.composition,
        "",
        INDEX_TEXT.composeIntro,
        "",
        ...composers.map((pkg) => composeLine(pkg.name, pkg.siblingDeps.join(PEER_JOIN))),
        "",
        INDEX_TEXT.standaloneIntro,
        "",
        ...leaves.map((pkg) =>
            standaloneLine(pkg.name, pkg.purpose === null ? pkg.description : firstSentence(pkg.purpose)),
        ),
    ];
};

export const renderIndexMarkdown = function renderIndexMarkdown(
    packages: readonly PackageInfo[],
    byGroup: ByGroup,
): string {
    const entrypoint = [relativePath("govlab.docs.entrypoints"), ENTRYPOINT_FILES.index].join(FOLDER_MARK);
    return [
        INDEX_HEADINGS.title,
        "",
        summaryOf(packages),
        "",
        INDEX_HEADINGS.groups,
        "",
        renderGroups(byGroup),
        "",
        INDEX_HEADINGS.tree,
        "",
        FENCE,
        renderTree(byGroup),
        FENCE,
        "",
        INDEX_HEADINGS.dependencies,
        "",
        FENCE,
        renderDependencies(packages),
        FENCE,
        "",
        INDEX_HEADINGS.inventory,
        "",
        renderInventory(packages),
        "",
        INDEX_HEADINGS.concerns,
        "",
        INDEX_TEXT.concernsNote,
        "",
        renderConcerns(packages),
        "",
        ...compositionLines(packages),
        "",
        INDEX_HEADINGS.reproduce,
        "",
        reproduceNote(entrypoint),
        "",
    ].join(LINE_BREAK);
};