core/converters/record.page.converter.ts
core/converters/record.page.converter.ts is a file in Bane's Lab Build Scripts. 133 lines of code and 38 definitions.
import {
CANONICAL_LABEL,
CLOSURE_LABEL,
CLOSURE_LINK_LABEL,
FORMED_BY_LABEL,
RECORD_LABEL,
SCOPE_LABEL,
SEVERITY_LABEL,
} from "@banes-lab/web/strings/ontology.strings";
import type { Identity, Link } from "#types/catalog.types";
import type { RecordData, RecordLeaf, RecordPageInput, RecordSubjectCounts } from "#types/record.types";
import type { RecordFact, RecordLink, RecordPlacement, RecordSubject } from "@banes-lab/web/types/page.types.js";
import { SITE_NAME, TITLE_SEPARATOR } from "@banes-lab/web/strings/page.strings";
import { missingAlternate, recordDescription } from "#configuration/strings/page.strings";
import { MARKDOWN_EXTENSION } from "#configuration/constants/site.constants";
import { RECORDS_SEGMENT } from "#configuration/constants/catalog.constants";
import { recordText } from "#core/selectors/record.selector";
const SLASH = "/";
const FRAGMENT = "#";
const HYPHEN = "-";
const SPACE = " ";
const RECORD_PREFIX = SLASH + RECORDS_SEGMENT + SLASH;
const isRecordLeaf = function isRecordLeaf(path: string): boolean {
return path.startsWith(RECORD_PREFIX) && path.endsWith(MARKDOWN_EXTENSION);
};
export const recordPathOf = function recordPathOf(identity: Identity): string {
const { markdown } = identity.address;
if (markdown === null || !isRecordLeaf(markdown)) {
throw new Error(missingAlternate(identity.ref));
}
return markdown.slice(0, -MARKDOWN_EXTENSION.length);
};
export const pageLinkOf = function pageLinkOf(site: string, link: Link): RecordLink {
const local = link.markdown?.startsWith(site) === true ? link.markdown.slice(site.length) : null;
if (local !== null && isRecordLeaf(local)) {
return { label: link.label, path: site + local.slice(0, -MARKDOWN_EXTENSION.length) };
}
return { label: link.label, path: link.href };
};
const tabPathOf = function tabPathOf(identity: Identity): string {
const href = identity.href ?? SLASH;
const cut = href.indexOf(FRAGMENT);
return cut === -1 ? href : href.slice(0, cut);
};
const anchorOf = function anchorOf(identity: Identity): string | null {
const href = identity.href ?? "";
const cut = href.indexOf(FRAGMENT);
return cut === -1 ? null : href.slice(cut + FRAGMENT.length);
};
const kindLabel = function kindLabel(kind: string): string {
return kind.split(HYPHEN).join(SPACE);
};
const headingOf = function headingOf(subject: Pick<RecordSubject, "code" | "name">): string {
return subject.code === null ? subject.name : `${subject.name} (${subject.code})`;
};
const countsOf = function countsOf(values: readonly string[]): ReadonlyMap<string, number> {
return values.reduce((counts, value) => counts.set(value, (counts.get(value) ?? 0) + 1), new Map<string, number>());
};
const isShared = function isShared(counts: ReadonlyMap<string, number>, value: string): boolean {
return (counts.get(value) ?? 0) > 1;
};
const distinctSubject = function distinctSubject(subject: RecordSubject, shared: RecordSubjectCounts): RecordSubject {
const kind = kindLabel(subject.kind);
const {label} = subject.collection;
const title = isShared(shared.titles, subject.title)
? [headingOf(subject), kind, label, SITE_NAME].join(TITLE_SEPARATOR)
: subject.title;
const description = isShared(shared.descriptions, subject.description)
? recordDescription(headingOf(subject), kind, label, subject.summary)
: subject.description;
return { ...subject, description, title };
};
export const distinctPages = function distinctPages(leaves: readonly RecordLeaf[]): readonly RecordLeaf[] {
const shared = {
descriptions: countsOf(leaves.map((leaf) => leaf.page.description)),
titles: countsOf(leaves.map((leaf) => leaf.page.title)),
};
return leaves.map((leaf) => ({ ...leaf, page: distinctSubject(leaf.page, shared) }));
};
const textFact = function textFact(data: RecordData, label: string, key: string): RecordFact | null {
const value = recordText(data, key);
return value === null ? null : { label, value: { label: value, path: null } };
};
const factsOf = function factsOf(data: RecordData, tabTitle: string): readonly RecordFact[] {
const closure = recordText(data, "closure");
const facts = [
{ label: RECORD_LABEL, value: { label: data.ref, path: null } },
textFact(data, SEVERITY_LABEL, "severity"),
textFact(data, SCOPE_LABEL, "scope"),
textFact(data, FORMED_BY_LABEL, "formedBy"),
data.href === null ? null : { label: CANONICAL_LABEL, value: { label: tabTitle, path: data.href } },
closure === null ? null : { label: CLOSURE_LABEL, value: { label: CLOSURE_LINK_LABEL, path: closure } },
];
return facts.filter((fact): fact is RecordFact => fact !== null);
};
const placementOf = function placementOf(data: RecordData, site: string): RecordPlacement | null {
if (data.up === null) {
return null;
}
const { next, previous } = data.siblings ?? { next: null, previous: null };
return {
next: next === null ? null : pageLinkOf(site, next),
previous: previous === null ? null : pageLinkOf(site, previous),
up: pageLinkOf(site, data.up),
};
};
export const recordSubjectOf = function recordSubjectOf(input: RecordPageInput): RecordSubject {
const { identity, record, site } = input;
const tabPath = tabPathOf(identity);
const tabTitle = input.tabLabel(tabPath);
const name = headingOf(record);
const path = recordPathOf(identity);
return {
aliases: input.aliases,
alternates: { json: identity.address.json, markdown: path + MARKDOWN_EXTENSION },
code: record.code,
collection: { label: tabTitle, path: tabPath },
description: record.summary ?? recordDescription(name, kindLabel(record.kind), tabTitle, null),
facts: factsOf(input.data, tabTitle),
kind: record.kind,
layer: input.layer === null ? null : pageLinkOf(site, input.layer),
name: record.name,
path,
placement: placementOf(input.data, site),
relations: input.relations.map((relation) => ({
links: relation.links.map((link) => pageLinkOf(site, link)),
relation: relation.relation,
})),
section: anchorOf(identity),
summary: record.summary,
title: name + TITLE_SEPARATOR + tabTitle + TITLE_SEPARATOR + SITE_NAME,
};
};