core/renderers/readme.renderer.ts
core/renderers/readme.renderer.ts is a file in Bane's Lab Content. 184 lines of code and 27 definitions.
import {
ADAPT_TEXT,
ADAPT_TITLE,
BY_AUTHOR,
CALLOUT_BODY,
CALLOUT_GRAMMAR,
CALLOUT_LEAD,
CALLOUT_TAIL,
CHAPTER_SUMMARIES,
CONTEXT_NOTE,
CONTEXT_TEXT,
CONTEXT_TITLE,
EXHIBIT_LEAD,
EXHIBIT_TITLE,
EXPECT_TEXT,
EXPECT_TITLE,
FORMAT_TEXT,
FORMAT_TITLE,
INTRO_TEXT,
LICENSED_UNDER,
LOOP_LEAD,
LOOP_TITLE,
MACHINE_BODY,
MACHINE_INDEX,
MACHINE_LEAD,
MACHINE_TAIL,
PROBLEM_ITEMS,
PROBLEM_LEAD,
PROBLEM_TITLE,
QUESTIONS_LEAD,
QUESTIONS_NOTE,
QUESTIONS_TITLE,
QUESTION_ITEMS,
READING_LEAD,
READING_TITLE,
SETUP_STEPS,
STANCE_ITEMS,
STANCE_LEAD,
STANCE_TAIL,
STANCE_TITLE,
START_LEAD,
START_TITLE,
WHY_ITEMS,
WHY_LEAD,
WHY_TITLE,
WORKS_LEAD,
WORKS_NOTE,
WORKS_TITLE,
} from "#configuration/strings/readme.strings";
import { ANATOMY_PAGE, GRAMMAR_PAGE } from "@banes-lab/web/core/ids/page.ids.ts";
import {
ANCHOR_MARK,
BOLD,
CENTER_CLOSE,
CENTER_OPEN,
FENCE_LANGUAGE,
HEADING_ONE,
HEADING_THREE,
ICON_SIZE,
LLMS_ROUTE,
LOGO_WIDTH,
QUOTE_MARK,
SENTENCE_END,
} from "#configuration/constants/readme.constants";
import { AUTHOR_PROFILE, METHODOLOGY_REPOSITORY, SITE_URL, pagePath } from "@banes-lab/web/core/assets/link.assets.ts";
import { BADGE_LOGO, LICENSE_BY, LICENSE_CC, LICENSE_SA } from "@banes-lab/web/core/assets/image.assets.ts";
import {
CHAPTER_SEPARATOR,
FENCE_MARK,
FOLDER_SEPARATOR,
LIST_ITEM,
NESTED_ITEM,
PARAGRAPH_BREAK,
} from "#configuration/constants/chapter.constants";
import { LOOP_SECTION_ID, STANCE_SECTION_ID } from "@banes-lab/web/core/ids/methodology.start.ids.ts";
import type { ReadmeInputs, ReadmePage, ReadmeSection, ReadmeStep, ReadmeTab } from "#types/readme.types";
import {
attributionLine,
bullets,
image,
link,
note,
numbered,
section,
tabFileOf,
} from "#core/renderers/markdown.renderer";
import { isRepositoryPage, pageFolderOf } from "#core/normalizers/readme.normalizer";
import type { Attribution } from "#types/chapter.types";
import { LINE_END } from "#configuration/constants/inventory.constants";
import { START_TAB } from "@banes-lab/web/core/ids/methodology.ids.ts";
import { renderFaq } from "#core/renderers/faq.renderer";
const ATTRIBUTION_SPACE = " ";
const ITEM_INDENT = " ";
const header = function header(inputs: ReadmeInputs, attribution: Attribution): string {
const owner =
link(inputs.heading, METHODOLOGY_REPOSITORY) +
ATTRIBUTION_SPACE +
attribution.copyright +
BY_AUTHOR +
link(attribution.author, AUTHOR_PROFILE);
const license = LICENSED_UNDER + link(attribution.licenseName, attribution.licenseUrl);
const icons = [LICENSE_CC, LICENSE_BY, LICENSE_SA].map((icon) => image(SITE_URL + icon, ICON_SIZE, "")).join("");
const logo = image(SITE_URL + BADGE_LOGO, LOGO_WIDTH, inputs.heading);
return [CENTER_OPEN, "", logo, "", owner + license + ATTRIBUTION_SPACE + icons, "", CENTER_CLOSE].join(LINE_END);
};
const callout = function callout(inputs: ReadmeInputs): string {
const grammar = inputs.exhibits.find((page) => page.page === GRAMMAR_PAGE);
const lines = [
CALLOUT_LEAD,
"",
CALLOUT_BODY + link(CALLOUT_GRAMMAR, SITE_URL + pagePath(GRAMMAR_PAGE)) + CALLOUT_TAIL,
"",
grammar?.description ?? "",
"",
MACHINE_LEAD,
"",
MACHINE_BODY + link(MACHINE_INDEX, SITE_URL + LLMS_ROUTE) + MACHINE_TAIL,
];
return lines.map((line) => (line.length === 0 ? QUOTE_MARK.trim() : QUOTE_MARK + line)).join(LINE_END);
};
const sectionsOf = function sectionsOf(page: ReadmePage): readonly ReadmeSection[] {
return page.tabs.flatMap((tab) => tab.sections);
};
const chapterEntry = function chapterEntry(tab: ReadmeTab): string {
const summary = CHAPTER_SUMMARIES.find((entry) => entry.tab === tab.id)?.summary ?? "";
return [HEADING_THREE + link(tab.label, tabFileOf(tab.id)), summary].join(PARAGRAPH_BREAK);
};
const works = function works(page: ReadmePage): string {
return section(WORKS_TITLE, WORKS_LEAD, WORKS_NOTE, ...page.tabs.map(chapterEntry));
};
const stance = function stance(): string {
const target = tabFileOf(START_TAB) + ANCHOR_MARK + STANCE_SECTION_ID;
const tail = STANCE_TAIL + link(STANCE_TITLE, target) + SENTENCE_END;
return section(STANCE_TITLE, STANCE_LEAD, numbered(STANCE_ITEMS), tail);
};
const exhibitChapters = function exhibitChapters(page: ReadmePage): string[] {
if (!isRepositoryPage(page.page)) {
return [];
}
const folder = pageFolderOf(page.page, page.title);
return page.tabs.map((tab) => NESTED_ITEM + link(tab.label, folder + FOLDER_SEPARATOR + tabFileOf(tab.id)));
};
const exhibits = function exhibits(inputs: ReadmeInputs): string {
const items = inputs.exhibits.flatMap((page) => [
LIST_ITEM + link(page.title, SITE_URL + pagePath(page.page)) + PARAGRAPH_BREAK + ITEM_INDENT + page.description,
...exhibitChapters(page),
]);
return section(EXHIBIT_TITLE, EXHIBIT_LEAD, items.join(LINE_END));
};
const stepGroup = function stepGroup(group: ReadmeStep): string {
return [HEADING_THREE + group.title, numbered(group.steps)].join(PARAGRAPH_BREAK);
};
const reading = function reading(page: ReadmePage): string {
return section(READING_TITLE, READING_LEAD, numbered(page.tabs.map((tab) => link(tab.label, tabFileOf(tab.id)))));
};
const loop = function loop(page: ReadmePage): string {
const diagram = sectionsOf(page).find((candidate) => candidate.id === LOOP_SECTION_ID)?.diagram;
if (diagram === null || diagram === undefined) {
return "";
}
return section(LOOP_TITLE, LOOP_LEAD, [FENCE_MARK + FENCE_LANGUAGE, diagram, FENCE_MARK].join(LINE_END));
};
export const renderReadme = function renderReadme(inputs: ReadmeInputs, attribution: Attribution): string {
const body = [
header(inputs, attribution),
callout(inputs),
[HEADING_ONE + inputs.heading, BOLD + inputs.subtitle + BOLD, INTRO_TEXT].join(PARAGRAPH_BREAK),
section(PROBLEM_TITLE, PROBLEM_LEAD, bullets(PROBLEM_ITEMS)),
works(inputs.methodology),
section(FORMAT_TITLE, FORMAT_TEXT),
stance(),
section(WHY_TITLE, WHY_LEAD, bullets(WHY_ITEMS)),
exhibits(inputs),
section(START_TITLE, START_LEAD, ...SETUP_STEPS.map(stepGroup)),
section(CONTEXT_TITLE, CONTEXT_TEXT, note(CONTEXT_NOTE, SITE_URL + pagePath(ANATOMY_PAGE))),
section(QUESTIONS_TITLE, QUESTIONS_LEAD, bullets(QUESTION_ITEMS), note(QUESTIONS_NOTE, SITE_URL + LLMS_ROUTE)),
section(ADAPT_TITLE, ADAPT_TEXT),
section(EXPECT_TITLE, EXPECT_TEXT),
reading(inputs.methodology),
loop(inputs.methodology),
renderFaq(inputs.faq),
].filter((part) => part.length > 0);
return body.join(CHAPTER_SEPARATOR) + CHAPTER_SEPARATOR + attributionLine(attribution) + LINE_END;
};