import type { ExampleValues } from '#shared/language/examples.ts'; import { toMorphemeValue } from '#shared/language/morphemes.ts'; import type { MorphemeValue } from '#shared/language/morphemes.ts'; import type { Numerus } from '#shared/nouns.ts'; export type GrammarTablesDefinition = (GrammarTableDefinition | string)[] | { simple: (GrammarTableDefinition | string)[]; comprehensive: (GrammarTableDefinition | string)[] }; export interface Header { name: string; short?: string; } export interface GrammarTableDefinition { columnHeader: Header[]; sections: SectionDefinition[]; } export interface SectionDefinition { header?: Header; variants: VariantDefinition[] | VariantsFromBaseDefinition; } export interface VariantDefinition { name?: string; cells: CellDefinition[]; } export interface VariantsFromBaseDefinition { base: string; type: string; } export type VariantsFromBaseConverter = Record Variant[]>; type CellDefinition = string | CellPartDefinition | CellPartDefinition[] | null; type CellPartDefinition = MorphemeCellDefinition | Record; export interface MorphemeCellDefinition { morpheme: string; highlightsMorphemes?: string[]; prefix?: MorphemeValue | string; suffix?: MorphemeValue | string; } export interface Variant { name?: string; numerus?: Numerus; icon?: string; cells: Cell[]; } export type Cell = CellPart[]; export interface CellPart { morpheme: string; highlightsMorphemes?: Set; prefix?: MorphemeValue; suffix?: MorphemeValue; } export const expandVariantsForSection = ( sectionVariants: SectionDefinition['variants'], variantsFromBaseConverter: VariantsFromBaseConverter, exampleValues: ExampleValues, ): Variant[] => { if (Array.isArray(sectionVariants)) { return sectionVariants.map((sectionVariant) => { const cells = sectionVariant.cells.map((cellDefinition) => { if (cellDefinition === null) { return []; } if (typeof cellDefinition === 'string') { return [{ morpheme: cellDefinition }]; } const cellPartDefinitions = Array.isArray(cellDefinition) ? cellDefinition : [cellDefinition]; return cellPartDefinitions .map((cellPartDefinition) => { if ('singular' in cellPartDefinition) { return cellPartDefinition[!exampleValues.plural ? 'singular' : 'plural']; } return cellPartDefinition; }) .map((cellPartDefinition) => ({ ...cellPartDefinition, prefix: cellPartDefinition.prefix ? toMorphemeValue(cellPartDefinition.prefix) : undefined, suffix: cellPartDefinition.suffix ? toMorphemeValue(cellPartDefinition.suffix) : undefined, highlightsMorphemes: cellPartDefinition.highlightsMorphemes ? new Set(cellPartDefinition.highlightsMorphemes) : undefined, })); }); return { ...sectionVariant, cells }; }); } else { if (Object.hasOwn(variantsFromBaseConverter, sectionVariants.type)) { return variantsFromBaseConverter[sectionVariants.type](sectionVariants); } throw new Error(`variant type ${sectionVariants.type} is unknown`); } };