import type { Concern, GrammarRoles, TaxonomySource, Vocabulary } from "../../types/taxonomy.types.ts"; const DEPTH_KEYS = ["depthOne", "depthTwo", "depthThree", "depthFour"] as const; const IMPORT_SELF = "."; export const importedRootsOf = function importedRootsOf(base: string, source: TaxonomySource): Map { const keys = new Set([ ...Object.keys(source.containers), ...Object.keys(source.specialContainers), ...Object.keys(source.foreignContainers ?? {}), ]); return new Map([...keys].map((key) => [key === IMPORT_SELF ? base : `${base}/${key}`, key])); }; const roleOf = function roleOf(token: string): string { return token.slice(1, -1); }; const grammarRolesOf = function grammarRolesOf(folder: Readonly>): GrammarRoles { const rolesAtDepth: string[][] = []; for (const key of DEPTH_KEYS) { const tokens = folder[key]; if (tokens === undefined) { break; } rolesAtDepth.push(tokens.map(roleOf)); } const roleOrder = [...new Set(rolesAtDepth.flat())]; return { roleOrder, rolesAtDepth, terminalRole: roleOrder.at(-1) ?? "" }; }; export const createVocabulary = function createVocabulary(source: TaxonomySource): Vocabulary { const byTag = new Map( source.concerns.flatMap((concern) => concern.collection === undefined ? [[concern.tag, concern] as const] : [[concern.tag, concern] as const, [concern.collection, concern] as const], ), ); const subjects = new Set(source.subjects); return { boundaryDocuments: new Set(source.boundaryDocuments), byFolder: new Map(source.concerns.map((concern) => [concern.folder, concern])), byTag, case: source.grammar.case, compoundMarkers: source.grammar.compoundMarkers, dialects: source.grammar.dialects ?? [], excludedTrees: source.Excluded?.trees ?? [], fileShapes: source.grammar.file, generatedFolder: source.grammar.generatedFolder ?? null, ignoredNames: source.Ignored.foldersFiles, legalSubjects: new Set([...subjects, ...byTag.keys()]), markerFolders: new Map(Object.entries(source.grammar.markerFolders ?? {})), maxDepth: source.grammar.maxDepthFromRoot, roles: grammarRolesOf(source.grammar.folder), separator: source.grammar.separator, splitters: new Map((source.grammar.splitters ?? []).map((splitter) => [splitter.name, splitter])), subjects, fixtureMarkers: source.grammar.fixtureMarkers ?? [], testMarkers: source.grammar.testMarkers ?? [], variants: new Set(source.variants), }; };