(grammar) allow multiple morphemes in a cell of a grammar table

This commit is contained in:
Valentyne Stigloher 2025-04-26 13:07:48 +02:00
parent f22148ceff
commit a3d4286c19
9 changed files with 170 additions and 166 deletions

View File

@ -15,23 +15,24 @@ const variantsFromBaseConverter = await loadGrammarTableVariantsConverter();
const expandVariantsForSection = (sectionVariants: SectionDefinition['variants']): Variant[] => { const expandVariantsForSection = (sectionVariants: SectionDefinition['variants']): Variant[] => {
if (Array.isArray(sectionVariants)) { if (Array.isArray(sectionVariants)) {
return sectionVariants.map((sectionVariant) => { return sectionVariants.map((sectionVariant) => {
const morphemeCells = sectionVariant.morphemeCells.map((morphemeCell) => { const cells = sectionVariant.morphemeCells.map((morphemeCell) => {
if (morphemeCell === null) { if (morphemeCell === null) {
return null; return [];
} }
if (typeof morphemeCell === 'string') { if (typeof morphemeCell === 'string') {
return { morpheme: morphemeCell }; return [{ morpheme: morphemeCell }];
} }
return { const morphemeDisplayDefinitions = Array.isArray(morphemeCell) ? morphemeCell : [morphemeCell];
return morphemeDisplayDefinitions.map((morphemeCell) => ({
...morphemeCell, ...morphemeCell,
prefix: morphemeCell.prefix ? toMorphemeValue(morphemeCell.prefix) : undefined, prefix: morphemeCell.prefix ? toMorphemeValue(morphemeCell.prefix) : undefined,
suffix: morphemeCell.suffix ? toMorphemeValue(morphemeCell.suffix) : undefined, suffix: morphemeCell.suffix ? toMorphemeValue(morphemeCell.suffix) : undefined,
highlightsMorphemes: morphemeCell.highlightsMorphemes highlightsMorphemes: morphemeCell.highlightsMorphemes
? new Set(morphemeCell.highlightsMorphemes) ? new Set(morphemeCell.highlightsMorphemes)
: undefined, : undefined,
}; }));
}); });
return { ...sectionVariant, morphemeCells }; return { ...sectionVariant, cells };
}); });
} else { } else {
if (Object.hasOwn(variantsFromBaseConverter, sectionVariants.type)) { if (Object.hasOwn(variantsFromBaseConverter, sectionVariants.type)) {
@ -45,9 +46,8 @@ const buildVariantsForSection = (
sectionVariants: SectionDefinition['variants'], sectionVariants: SectionDefinition['variants'],
): Variant[] => { ): Variant[] => {
return expandVariantsForSection(sectionVariants).filter((variant) => { return expandVariantsForSection(sectionVariants).filter((variant) => {
return variant.morphemeCells.some((morphemeCell) => { return variant.cells.flatMap((cell) => cell).some((morphemeDisplay) => {
return morphemeCell !== null && return props.exampleValues.morphemeValues.getSpelling(morphemeDisplay.morpheme) !== undefined;
props.exampleValues.morphemeValues.getSpelling(morphemeCell.morpheme) !== undefined;
}); });
}); });
}; };
@ -129,20 +129,24 @@ const rowHeaderCount = computed(() => {
</th> </th>
</template> </template>
</template> </template>
<td v-for="(morphemeCell, index) in variant.morphemeCells" :key="index"> <td v-for="(cell, index) in variant.cells" :key="index">
<MorphemeWithPronunciation <template v-for="(morphemeDisplay, morphemeIndex) in cell" :key="morphemeIndex">
v-if="morphemeCell !== null" <template v-if="morphemeIndex > 0">
:morpheme="morphemeCell.morpheme" /
:example-values </template>
:prefix="morphemeCell.prefix" <MorphemeWithPronunciation
:suffix="morphemeCell.suffix" :morpheme="morphemeDisplay.morpheme"
:highlights-morphemes="morphemeCell.highlightsMorphemes" :example-values
:examples :prefix="morphemeDisplay.prefix"
/> :suffix="morphemeDisplay.suffix"
:highlights-morphemes="morphemeDisplay.highlightsMorphemes"
:examples
/>
</template>
</td> </td>
<td <td
v-if="grammarTable.columnHeader.length > variant.morphemeCells.length" v-if="grammarTable.columnHeader.length > variant.cells.length"
:colspan="grammarTable.columnHeader.length - variant.morphemeCells.length" :colspan="grammarTable.columnHeader.length - variant.cells.length"
></td> ></td>
</tr> </tr>
</template> </template>

View File

@ -1,4 +1,4 @@
import type { MorphemeCell, VariantsFromBaseConverter } from '~/src/language/grammarTables.ts'; import type { Cell, MorphemeDisplay, VariantsFromBaseConverter } from '~/src/language/grammarTables.ts';
const cases = ['n', 'g', 'd', 'a']; const cases = ['n', 'g', 'd', 'a'];
@ -72,27 +72,27 @@ const adjectiveDeclensions: Category[] = [
const morphemesByCase = ( const morphemesByCase = (
morphemeBase: string, morphemeBase: string,
attributes: Pick<MorphemeCell, 'prefix' | 'suffix'> = {}, attributes: Pick<MorphemeDisplay, 'prefix' | 'suffix'> = {},
): MorphemeCell[] => { ): Cell[] => {
return cases.map((caseAbbreviation) => ({ morpheme: `${morphemeBase}_${caseAbbreviation}`, ...attributes })); return cases.map((caseAbbreviation) => [{ morpheme: `${morphemeBase}_${caseAbbreviation}`, ...attributes }]);
}; };
export default { export default {
'case': (sectionVariants) => { 'case': (sectionVariants) => {
return [{ morphemeCells: morphemesByCase(sectionVariants.base) }]; return [{ cells: morphemesByCase(sectionVariants.base) }];
}, },
'declension-with-case': (sectionVariants) => { 'declension-with-case': (sectionVariants) => {
return declensions.map((declension) => ({ return declensions.map((declension) => ({
name: declension.name, name: declension.name,
numerus: declension.numerus, numerus: declension.numerus,
icon: declension.icon, icon: declension.icon,
morphemeCells: morphemesByCase(`${sectionVariants.base}_${declension.abbreviation}`), cells: morphemesByCase(`${sectionVariants.base}_${declension.abbreviation}`),
})); }));
}, },
'definiteness-with-case': (sectionVariants) => { 'definiteness-with-case': (sectionVariants) => {
return definitenessCategories.map((definitenessCategory) => ({ return definitenessCategories.map((definitenessCategory) => ({
name: definitenessCategory.name, name: definitenessCategory.name,
morphemeCells: morphemesByCase(`${definitenessCategory.abbreviation}${sectionVariants.base}`), cells: morphemesByCase(`${definitenessCategory.abbreviation}${sectionVariants.base}`),
})); }));
}, },
'adjective-declension-with-case': (sectionVariants) => { 'adjective-declension-with-case': (sectionVariants) => {
@ -100,7 +100,7 @@ export default {
const morphemeBase = `${sectionVariants.base}_${adjectiveDeclension.abbreviation}`; const morphemeBase = `${sectionVariants.base}_${adjectiveDeclension.abbreviation}`;
return { return {
name: adjectiveDeclension.name, name: adjectiveDeclension.name,
morphemeCells: morphemesByCase(morphemeBase, { prefix: { spelling: '-' } }), cells: morphemesByCase(morphemeBase, { prefix: { spelling: '-' } }),
}; };
}); });
}, },

View File

@ -23,6 +23,73 @@ pronouns:
- 'adjective' - 'adjective'
- 'possessive' - 'possessive'
- 'definitive' - 'definitive'
grammarTables:
-
columnHeader:
-
name: 'именительный'
-
name: 'родительный'
-
name: 'дательный'
-
name: 'винительный'
-
name: 'творительный'
-
name: 'предложный'
sections:
-
variants:
-
morphemeCells:
- 'nominative'
-
-
morpheme: 'genitive'
-
morpheme: 'genitive_with_preposition'
- 'dative'
- 'accusative'
-
-
morpheme: 'instrumental'
-
morpheme: 'instrumental_with_preposition'
- 'prepositional'
-
columnHeader:
-
name: 'Окончание невозвратных глаголов в пр. в.'
-
name: 'Окончание возвратных глаголов в пр. в.'
-
name: 'Окончание кратких прилагательных'
-
name: 'Окончание прилагательных'
-
name: 'Притяжательное местоимение'
-
name: 'Определительное местоимение'
sections:
-
variants:
-
morphemeCells:
-
morpheme: 'nonreflexive_verb_past'
prefix: ''
-
morpheme: 'reflexive_verb_past'
prefix: ''
-
morpheme: 'short_adjective'
prefix: ''
-
morpheme: 'adjective'
prefix: ''
- 'possessive'
- 'definitive'
route: 'pronouns' route: 'pronouns'
any: 'any' any: 'any'
plurals: true plurals: true

View File

@ -1,67 +0,0 @@
<template>
<section>
<h2 class="h4">
<Icon v="spell-check" />
Грамматика:
</h2>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>именительный</th>
<th>родительный</th>
<th>дательный</th>
<th>винительный</th>
<th>творительный</th>
<th>предложный</th>
</tr>
</thead>
<tbody>
<tr>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="nominative" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="genitive" :counter="counter" /> / <PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="genitive_with_preposition" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="dative" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="accusative" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="instrumental" :counter="counter" /> / <PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="instrumental_with_preposition" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="prepositional" :counter="counter" /></td>
</tr>
</tbody>
</table>
</div>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>Окончание невозвратных глаголов в пр. в.</th>
<th>Окончание возвратных глаголов в пр. в.</th>
<th>Окончание кратких прилагательных</th>
<th>Окончание прилагательных</th>
<th>Притяжательное местоимение</th>
<th>Определительное местоимение</th>
</tr>
</thead>
<tbody>
<tr>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="nonreflexive_verb_past" :counter="counter" prepend="" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="reflexive_verb_past" :counter="counter" prepend="" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="short_adjective" :counter="counter" prepend="" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="adjective" :counter="counter" prepend="" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="definitive" :counter="counter" /></td>
</tr>
</tbody>
</table>
</div>
</section>
</template>
<script>
export default {
props: {
selectedPronoun: { required: true },
counter: { required: true },
},
};
</script>

View File

@ -102,7 +102,7 @@ pronouns:
others: 'Другие формы' others: 'Другие формы'
othersRaw: 'другие' othersRaw: 'другие'
or: 'или' or: 'или'
grammarTable: 'Таблица' grammarTable: 'Грамматика'
pronunciation: pronunciation:
play: 'Включить аудио-сэмпл' play: 'Включить аудио-сэмпл'

View File

@ -23,6 +23,69 @@ pronouns:
- 'adjective' - 'adjective'
- 'possessive' - 'possessive'
- 'definitive' - 'definitive'
grammarTables:
-
columnHeader:
-
name: 'називний'
-
name: 'родовий'
-
name: 'давальний'
-
name: 'знахідний'
-
name: 'орудний'
-
name: 'місцевий'
sections:
-
variants:
-
morphemeCells:
- 'nominative'
-
-
morpheme: 'genitive'
-
morpheme: 'genitive_with_preposition'
- 'dative'
- 'accusative'
-
-
morpheme: 'instrumental'
-
morpheme: 'instrumental_with_preposition'
- 'prepositional'
-
columnHeader:
-
name: 'Закінчення незворотніх дієслів'
-
name: 'Закінчення зворотніх дієслів'
-
name: 'Закінчення прикметників'
-
name: 'Присвійний займенник'
-
name: 'Означальний займенник'
sections:
-
variants:
-
morphemeCells:
-
morpheme: 'nonreflexive_verb_past'
prefix: ''
-
morpheme: 'reflexive_verb_past'
prefix: ''
-
morpheme: 'adjective'
prefix: ''
- 'possessive'
- 'definitive'
route: 'pronouns' route: 'pronouns'
any: 'будь-які' any: 'будь-які'
plurals: true plurals: true

View File

@ -1,65 +0,0 @@
<template>
<section>
<h2 class="h4">
<Icon v="spell-check" />
Граматика:
</h2>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>називний</th>
<th>родовий</th>
<th>давальний</th>
<th>знахідний</th>
<th>орудний</th>
<th>місцевий</th>
</tr>
</thead>
<tbody>
<tr>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="nominative" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="genitive" :counter="counter" /> / <PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="genitive_with_preposition" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="dative" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="accusative" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="instrumental" :counter="counter" /> / <PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="instrumental_with_preposition" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="prepositional" :counter="counter" /></td>
</tr>
</tbody>
</table>
</div>
<div class="table-responsive">
<table class="table table-sm">
<thead>
<tr>
<th>Закінчення незворотніх дієслів</th>
<th>Закінчення зворотніх дієслів</th>
<th>Закінчення прикметників</th>
<th>Присвійний займенник</th>
<th>Означальний займенник</th>
</tr>
</thead>
<tbody>
<tr>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="nonreflexive_verb_past" :counter="counter" prepend="" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="reflexive_verb_past" :counter="counter" prepend="" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="adjective" :counter="counter" prepend="" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="possessive" :counter="counter" /></td>
<td><PronounsMorphemeWithPronunciation :pronoun="selectedPronoun" morpheme="definitive" :counter="counter" /></td>
</tr>
</tbody>
</table>
</div>
</section>
</template>
<script>
export default {
props: {
selectedPronoun: { required: true },
counter: { required: true },
},
};
</script>

View File

@ -76,7 +76,7 @@ pronouns:
others: 'Інші форми' others: 'Інші форми'
othersRaw: 'інші' othersRaw: 'інші'
or: 'або' or: 'або'
grammarTable: 'Таблиця' grammarTable: 'Граматика'
null: null:
header: header:
avoiding: 'Уникнення ґендерних форм' avoiding: 'Уникнення ґендерних форм'

View File

@ -20,7 +20,7 @@ export interface SectionDefinition {
export interface VariantDefinition { export interface VariantDefinition {
name?: string; name?: string;
morphemeCells: (string | MorphemeCellDefinition | null)[]; morphemeCells: (string | MorphemeCellDefinition | MorphemeCellDefinition[] | null)[];
} }
export interface VariantsFromBaseDefinition { export interface VariantsFromBaseDefinition {
@ -41,10 +41,12 @@ export interface Variant {
name?: string; name?: string;
numerus?: 'singular' | 'plural'; numerus?: 'singular' | 'plural';
icon?: string; icon?: string;
morphemeCells: (MorphemeCell | null)[]; cells: Cell[];
} }
export interface MorphemeCell { export type Cell = MorphemeDisplay[];
export interface MorphemeDisplay {
morpheme: string; morpheme: string;
highlightsMorphemes?: Set<string>; highlightsMorphemes?: Set<string>;
prefix?: MorphemeValue; prefix?: MorphemeValue;