import { CONCERNS_LABEL, DISCRIMINATOR_LABEL, DISTINGUISHES_LABEL, FORCE_INTRO, FORCE_TITLE, KINDS_IN_RANGE_LABEL, KIND_INTRO, KIND_TITLE, PRINCIPLES_OF_KIND_LABEL, RANGE_CAPTION, RANGE_INTRO, RANGE_SECTION_TITLE, SIGNATURES_LABEL, TERMS_OF_KIND_LABEL, } from "#configuration/strings/kind.strings"; import { CONTRACTS_LABEL, PRINCIPLES_LABEL } from "#configuration/strings/ontology.strings"; import { FORCE_ANCHOR, FORCE_SECTION_ID, KIND_ANCHOR, KIND_SECTION_ID, RANGE_SECTION_ID, RELATION_ANCHOR, } from "#core/ids/ontology.ids"; import type { ForceView, KindView, RelationRangeView } from "#types/ontology.types"; import type { Section, Subsection } from "#types/document.types"; import { chips, diagram, edgeLine, glossary, labelled, linkList, node, plainList, row, text, } from "#domain/converters/ontology.converter"; import { KIND_SECTION_ICON } from "#configuration/icons/ontology.icons"; const HEADER = "flowchart LR"; const SOLID = " --> "; const RELATION_PREFIX = "relation-"; const UNDERSCORE = "_"; const SPACE = " "; const kindSubsection = function kindSubsection(kind: KindView): Subsection { return { blocks: [ chips([ labelled(PRINCIPLES_OF_KIND_LABEL, String(kind.principles)), labelled(TERMS_OF_KIND_LABEL, String(kind.terms)), ]), glossary([ row(DISCRIMINATOR_LABEL, kind.discriminator), row(DISTINGUISHES_LABEL, kind.distinguishesFrom), row(SIGNATURES_LABEL, plainList(kind.definitionSignatures)), ]), ], id: KIND_ANCHOR + kind.kind, title: kind.kind, }; }; const kindSection = function kindSection(kinds: readonly KindView[], resolutionNote: string): Section { return { blocks: [text(resolutionNote)], icon: KIND_SECTION_ICON, id: KIND_SECTION_ID, intro: KIND_INTRO, subsections: kinds.map(kindSubsection), title: KIND_TITLE, }; }; const rangeDiagram = function rangeDiagram(ranges: readonly RelationRangeView[], kinds: readonly KindView[]): string { const relationNodes = ranges.map((range) => node(RELATION_PREFIX + range.relation, range.relation)); const kindNodes = kinds.map((kind) => node(kind.kind, kind.kind)); const edges = ranges.flatMap((range) => range.kinds.map((kind) => edgeLine(RELATION_PREFIX + range.relation, SOLID, kind.label)), ); return diagram(HEADER, [...relationNodes, ...kindNodes, ...edges]); }; const rangeSection = function rangeSection(ranges: readonly RelationRangeView[], kinds: readonly KindView[]): Section { return { blocks: [{ caption: RANGE_CAPTION, kind: "mermaid", text: rangeDiagram(ranges, kinds) }], icon: KIND_SECTION_ICON, id: RANGE_SECTION_ID, intro: RANGE_INTRO, subsections: ranges.map((range) => ({ blocks: [glossary([row(KINDS_IN_RANGE_LABEL, linkList(range.kinds))])], id: RELATION_ANCHOR + range.relation, title: range.relation, })), title: RANGE_SECTION_TITLE, }; }; const forceSubsection = function forceSubsection(force: ForceView): Subsection { return { blocks: [ glossary([ row(CONTRACTS_LABEL, linkList(force.contracts)), row(PRINCIPLES_LABEL, linkList(force.principles)), ...(force.concerns.length === 0 ? [] : [row(CONCERNS_LABEL, plainList(force.concerns))]), ]), ], id: FORCE_ANCHOR + force.id, title: force.force.replaceAll(UNDERSCORE, SPACE), }; }; const forceSection = function forceSection(forces: readonly ForceView[]): Section { return { icon: KIND_SECTION_ICON, id: FORCE_SECTION_ID, intro: FORCE_INTRO, subsections: forces.map(forceSubsection), title: FORCE_TITLE, }; }; export const kindSections = function kindSections( kinds: readonly KindView[], ranges: readonly RelationRangeView[], forces: readonly ForceView[], resolutionNote: string, ): readonly Section[] { return [kindSection(kinds, resolutionNote), rangeSection(ranges, kinds), forceSection(forces)]; };