presentation/renderers/block.renderer.ts
presentation/renderers/block.renderer.ts is a file in Bane's Lab Site. 177 lines of code and 20 definitions.
import type {
Block,
CardBlock,
CodeBlock,
DefinitionBlock,
FigureBlock,
GlossaryBlock,
GroupBlock,
GroupEntry,
LessonBlock,
LinkBlock,
ListBlock,
MarkdownBlock,
MermaidBlock,
MetricBlock,
SourceBlock,
SurfaceBlock,
TableBlock,
TextBlock,
WalkBlock,
} from "#types/block.types";
import { appendChildren, createElement } from "#core/factories/element.factory";
import type { GrammarBlock } from "#types/grammar.types";
import { createCodeBlock } from "#presentation/components/code.component";
import { fillMarkup } from "#presentation/renderers/text.renderer";
import { renderCards } from "#presentation/renderers/card.renderer";
import { renderDefinition } from "#presentation/renderers/definition.renderer";
import { renderDiagram } from "#presentation/renderers/diagram.renderer";
import { renderDocument } from "#presentation/renderers/markdown.renderer";
import { renderFigure } from "#presentation/renderers/figure.renderer";
import { renderGlossary } from "#presentation/renderers/glossary.block.renderer";
import { renderGrammarBlock } from "#presentation/renderers/grammar.renderer";
import { renderLesson } from "#presentation/renderers/lesson.renderer";
import { renderLinks } from "#presentation/renderers/link.renderer";
import { renderMetrics } from "#presentation/renderers/metric.renderer";
import { renderSource } from "#presentation/renderers/source.renderer";
import { renderSurface } from "#presentation/renderers/surface.renderer";
import { renderTable } from "#presentation/renderers/table.renderer";
import { renderWalk } from "#presentation/renderers/walk.renderer";
const renderText = function renderText(block: TextBlock): Element {
const className = block.note === true ? "block-note" : "block-text";
return fillMarkup(createElement("p", { className }), block.text);
};
const renderList = function renderList(block: ListBlock): Element {
const wrapper = createElement("div", { className: "block-list" });
if (block.label !== undefined) {
wrapper.append(createElement("h4", { className: "block-label", text: block.label }));
}
const list = createElement(block.ordered === true ? "ol" : "ul", {});
appendChildren(
list,
block.items.map((item) => fillMarkup(createElement("li", {}), item)),
);
wrapper.append(list);
return wrapper;
};
const renderGroup = function renderGroup(group: GroupEntry): Element {
const wrapper = createElement("div", { className: "block-group" });
if (group.title !== undefined) {
wrapper.append(fillMarkup(createElement("h4", { className: "block-label" }), group.title));
}
if (group.content !== undefined) {
wrapper.append(fillMarkup(createElement("p", { className: "block-text" }), group.content));
}
if (group.items !== undefined) {
wrapper.append(renderList({ items: group.items, kind: "list" }));
}
if (group.entries !== undefined) {
wrapper.append(renderGlossary({ entries: group.entries, kind: "glossary" }));
}
return wrapper;
};
const renderGroups = function renderGroups(block: GroupBlock): Element {
const className = block.tone === undefined ? "block-groups" : `block-groups ${block.tone}`;
const wrapper = createElement("div", { className });
appendChildren(wrapper, block.groups.map(renderGroup));
return wrapper;
};
type CompositeBlock = CardBlock | FigureBlock | LessonBlock | MermaidBlock | MetricBlock | SurfaceBlock | WalkBlock;
type CodedBlock = CodeBlock | DefinitionBlock | MarkdownBlock | SourceBlock;
const renderCoded = function renderCoded(block: CodedBlock): Element {
switch (block.kind) {
case "code": {
return createCodeBlock(block.code, block.title, block.language);
}
case "source": {
return renderSource(block);
}
case "markdown": {
return renderDocument(block);
}
case "definition": {
return renderDefinition(block);
}
default: {
return renderDefinition(block);
}
}
};
const renderComposite = function renderComposite(block: CompositeBlock): Element {
switch (block.kind) {
case "card": {
return renderCards(block);
}
case "lesson": {
return renderLesson(block);
}
case "figure": {
return renderFigure(block);
}
case "mermaid": {
return renderDiagram(block);
}
case "walk": {
return renderWalk(block);
}
case "surface": {
return renderSurface(block);
}
case "metric": {
return renderMetrics(block);
}
default: {
return renderMetrics(block);
}
}
};
type SimpleBlock = GlossaryBlock | GroupBlock | LinkBlock | ListBlock | TableBlock | TextBlock;
const COMPOSITE_KINDS = new Set<Block["kind"]>(["card", "figure", "lesson", "mermaid", "metric", "surface", "walk"]);
const CODED_KINDS = new Set<Block["kind"]>(["code", "definition", "markdown", "source"]);
const GRAMMAR_KINDS = new Set<Block["kind"]>(["check", "compare", "diagram", "keyword", "type"]);
const isComposite = function isComposite(block: Block): block is CompositeBlock {
return COMPOSITE_KINDS.has(block.kind);
};
const isCoded = function isCoded(block: Block): block is CodedBlock {
return CODED_KINDS.has(block.kind);
};
const isGrammar = function isGrammar(block: Block): block is GrammarBlock {
return GRAMMAR_KINDS.has(block.kind);
};
const renderSimple = function renderSimple(block: SimpleBlock): Element {
switch (block.kind) {
case "text": {
return renderText(block);
}
case "list": {
return renderList(block);
}
case "glossary": {
return renderGlossary(block);
}
case "table": {
return renderTable(block);
}
case "group": {
return renderGroups(block);
}
case "link": {
return renderLinks(block);
}
default: {
return renderLinks(block);
}
}
};
export const renderBlock = function renderBlock(block: Block): Element {
if (isGrammar(block)) {
return renderGrammarBlock(block);
}
if (isCoded(block)) {
return renderCoded(block);
}
if (isComposite(block)) {
return renderComposite(block);
}
return renderSimple(block);
};