import { ANATOMY_CONTAINER_ICON, FOLDER_SECTION_ICON } from "#configuration/icons/anatomy.icons"; import type { AnatomyFile, AnatomyFolder, AnatomySnapshot, DefinitionRef, DefinitionView } from "#types/anatomy.types"; import { CALLED_BY_LABEL, CALLS_LABEL, CONCERN_LABEL, DOCUMENT_TITLE, FILE_WALK_CAPTION, FOLDER_INTRO_DEFINITIONS, FOLDER_INTRO_EDGES, FOLDER_INTRO_FILES, FOLDER_INTRO_HOLDING, FOLDER_INTRO_LAYER_TAIL, FOLDER_INTRO_LEAD, FOLDER_INTRO_LINES, FOLDER_INTRO_ON_LAYER, FOLDER_WALK_CAPTION, GENERATED_LABEL, INHERITED_LABEL, IN_LABEL, LAYER_LABEL, LINE_MARK, OUT_LABEL, RARE_SYNTAX_LABEL, ROOT_LABEL, SOURCE_TITLE, STATS_LABEL, SUBJECT_LABEL, SYNTAX_LABEL, TREE_LABEL, UNPARSED_LABEL, VARIANT_LABEL, } from "#configuration/strings/folder.strings"; import { LABEL_SEPARATOR, LIST_SEPARATOR, NONE_LABEL } from "#configuration/strings/ontology.strings"; import type { Section, Subsection, Tab } from "#types/document.types"; import { chips, glossary, labelled, row } from "#domain/converters/ontology.converter"; import { documentBlocks, documentChips } from "#domain/converters/document.converter"; import { fileId, folderId, languageOf, nodeHref } from "#domain/converters/source.converter"; import type { Block } from "#types/block.types"; import { STATS_SEPARATOR } from "#configuration/constants/anatomy.constants"; import { TREE_TAB } from "#core/ids/anatomy.ids"; import { statsMetrics } from "#domain/converters/anatomy.fragment.converter"; const BREAK = "
"; const refLink = function refLink(ref: DefinitionRef): string { return `${ref.name}`; }; const refList = function refList(refs: readonly DefinitionRef[]): string { return refs.length === 0 ? NONE_LABEL : refs.map(refLink).join(LIST_SEPARATOR); }; const mark = function mark(label: string, value: string): string { return `${label} ${value}`; }; const definitionRow = function definitionRow(definition: DefinitionView): ReturnType { const head = [ `${definition.flow}`, mark(IN_LABEL, String(definition.inDegree)), mark(OUT_LABEL, String(definition.outDegree)), ].join(STATS_SEPARATOR); const description = [ head, CALLS_LABEL + LABEL_SEPARATOR + refList(definition.callees), CALLED_BY_LABEL + LABEL_SEPARATOR + refList(definition.callers), ].join(BREAK); return row(definition.name + LINE_MARK + String(definition.line), description); }; const fileChips = function fileChips(file: AnatomyFile): Block { return chips([ file.slots === null ? UNPARSED_LABEL : labelled(SUBJECT_LABEL, file.slots.subject), file.slots === null ? null : labelled(CONCERN_LABEL, file.slots.concern), file.slots === null ? null : labelled(VARIANT_LABEL, file.slots.variant), labelled(LAYER_LABEL, file.layer), file.generated ? GENERATED_LABEL : null, file.inherited ? INHERITED_LABEL : null, ...documentChips(file.document), ]); }; const distributionBlocks = function distributionBlocks(file: AnatomyFile): Block[] { const kinds = file.distribution.invariants.map((stat) => ({ label: stat.type, value: String(stat.count) })); const rare = file.distribution.variants.map((stat) => ({ label: stat.type, value: String(stat.count) })); return [ ...(kinds.length === 0 ? [] : [{ caption: SYNTAX_LABEL, kind: "metric" as const, metrics: kinds }]), ...(rare.length === 0 ? [] : [{ caption: RARE_SYNTAX_LABEL, kind: "metric" as const, metrics: rare }]), ]; }; const fileBlocks = function fileBlocks(file: AnatomyFile): Block[] { return [ fileChips(file), { caption: STATS_LABEL, kind: "metric" as const, metrics: statsMetrics(file.stats) }, ...(file.definitions.length === 0 ? [] : [glossary(file.definitions.map(definitionRow))]), ...(file.document === null ? [] : documentBlocks(file.document)), ...(file.walk === null ? [] : [{ caption: FILE_WALK_CAPTION, kind: "walk" as const, walk: file.walk }]), ...distributionBlocks(file), ...(file.source === null || file.document === null ? [] : [{ kind: "markdown" as const, path: file.path, source: file.source, title: DOCUMENT_TITLE }]), ...(file.source === null ? [] : [ { kind: "source" as const, language: languageOf(file.name), path: file.path, source: file.source, title: SOURCE_TITLE, }, ]), ]; }; const fileRecord = function fileRecord(file: AnatomyFile): Subsection { return { blocks: fileBlocks(file), id: fileId(file.path), title: file.name }; }; const count = function count(value: number): string { return `${String(value)}`; }; const folderIntro = function folderIntro(folder: AnatomyFolder): string { const layer = folder.layer === null ? "" : `${FOLDER_INTRO_ON_LAYER}${folder.layer}${FOLDER_INTRO_LAYER_TAIL}`; const counts = [ count(folder.stats.files) + FOLDER_INTRO_FILES, count(folder.stats.lines.code) + FOLDER_INTRO_LINES, count(folder.stats.definitions) + FOLDER_INTRO_DEFINITIONS, count(folder.stats.edges) + FOLDER_INTRO_EDGES, ].join(""); return `${FOLDER_INTRO_LEAD}${folder.role}${layer}${FOLDER_INTRO_HOLDING}${counts}`; }; const folderSection = function folderSection(folder: AnatomyFolder): Section { return { blocks: [ { caption: STATS_LABEL, kind: "metric" as const, metrics: statsMetrics(folder.stats) }, ...(folder.walk === null ? [] : [{ caption: FOLDER_WALK_CAPTION, kind: "walk" as const, walk: folder.walk }]), ], icon: FOLDER_SECTION_ICON, id: folderId(folder.path), intro: folderIntro(folder), subsections: folder.files.map(fileRecord), title: folder.path === "" ? ROOT_LABEL : folder.path, }; }; const folderSections = function folderSections(folder: AnatomyFolder): Section[] { return [folderSection(folder), ...folder.folders.flatMap(folderSections)]; }; export const treeTab = function treeTab(snapshot: AnatomySnapshot): Tab { return { icon: ANATOMY_CONTAINER_ICON, id: TREE_TAB, label: TREE_LABEL, layout: "tree", sections: folderSections(snapshot.tree), }; };