mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-09-26 22:43:06 -04:00
201 lines
8.0 KiB
Vue
201 lines
8.0 KiB
Vue
<script setup lang="ts">
|
|
import { ExampleCategory, Pronoun } from '~/src/classes.ts';
|
|
import Compressor from '~/src/compressor.ts';
|
|
import { loadPronounExamples, loadPronounLibrary } from '~/src/data.ts';
|
|
|
|
const config = useConfig();
|
|
if (!config.pronouns.enabled || !config.pronouns.generator.enabled) {
|
|
throw new Error('config.pronouns.generator is disabled');
|
|
}
|
|
|
|
const { $translator: translator } = useNuxtApp();
|
|
|
|
const [pronounLibrary, examples] = await Promise.all([loadPronounLibrary(config), loadPronounExamples()]);
|
|
const pronouns = pronounLibrary.pronouns;
|
|
|
|
const exampleCategories = ExampleCategory.from(examples, config);
|
|
const examplesByHonorific = [false, true].map((isHonorific) => {
|
|
const examples = exampleCategories
|
|
.filter((exampleCategory) => !exampleCategory.comprehensive && exampleCategory.examples.length > 0)
|
|
.map((exampleCategory) => exampleCategory.examples[0])
|
|
.filter((example) => example.isHonorific === isHonorific);
|
|
return { examples, isHonorific };
|
|
}).filter(({ examples }) => examples.length > 0);
|
|
|
|
const selectedPronoun = ref(pronouns[config.pronouns.generator.startPronoun].clone(true));
|
|
const selectedMorpheme = ref('');
|
|
|
|
const glue = ` ${translator.translate('pronouns.or')} `;
|
|
|
|
const deduplicatePronounGroup = (pronounGroup: Pronoun[]): Pronoun[] => {
|
|
const dict: Record<string, Pronoun> = {};
|
|
for (const pronoun of pronounGroup) {
|
|
if (Object.hasOwn(dict, pronoun.name(glue))) {
|
|
continue;
|
|
}
|
|
dict[pronoun.name(glue)] = pronoun;
|
|
}
|
|
return Object.values(dict);
|
|
};
|
|
|
|
const usedBase = computed((): string | null => {
|
|
const name = selectedPronoun.value.name(glue);
|
|
for (const key in pronouns) {
|
|
if (Object.hasOwn(pronouns, key)) {
|
|
if (key === name) {
|
|
return key;
|
|
}
|
|
for (const alias of pronouns[key].aliases) {
|
|
if (alias === name) {
|
|
return key;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
});
|
|
const usedBaseEquals = computed((): boolean => {
|
|
return !!usedBase.value && selectedPronoun.value.equals(pronouns[usedBase.value], true);
|
|
});
|
|
|
|
const longPath = computed((): string => {
|
|
const base = pronouns[selectedPronoun.value.morphemes[config.pronouns.morphemes![0]]!];
|
|
|
|
return base
|
|
? Compressor.compress(
|
|
selectedPronoun.value.toArray().map((x) => x.split('|')[0]),
|
|
base.toArray().map((x) => x.split('|')[0]),
|
|
).join(',')
|
|
: selectedPronoun.value.toString();
|
|
});
|
|
const path = computed((): string | null => {
|
|
if (!selectedPronoun.value.pronoun()) {
|
|
return null;
|
|
}
|
|
|
|
const slashes = selectedPronoun.value.toStringSlashes(translator);
|
|
|
|
if (usedBaseEquals.value) {
|
|
return usedBase.value;
|
|
} else if (slashes) {
|
|
return slashes;
|
|
} else {
|
|
return longPath.value;
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<PronounsGenerator
|
|
v-if="config.pronouns.enabled && config.pronouns.generator.enabled"
|
|
type="generator"
|
|
:path="path"
|
|
:initially-open="config.pronouns.generator.autoOpen ?? false"
|
|
:disclaimer="!usedBaseEquals"
|
|
>
|
|
<div class="card-title border-bottom pb-3">
|
|
<p><strong><T>home.generator.base</T><T>quotation.colon</T></strong></p>
|
|
<ul class="list-unstyled">
|
|
<template v-for="[group, groupPronouns] in pronounLibrary.split()" :key="group.key">
|
|
<li v-if="!group.hidden">
|
|
<ul class="list-inline">
|
|
<li class="list-inline-item">
|
|
<Spelling :text="group.name" />
|
|
</li>
|
|
<template
|
|
v-for="pronoun in deduplicatePronounGroup(groupPronouns)"
|
|
:key="pronoun.canonicalName"
|
|
>
|
|
<li v-if="!pronoun.hidden" class="list-inline-item">
|
|
<button
|
|
type="button"
|
|
:class="['btn', pronoun.name(glue) === selectedPronoun.name(glue) ? 'btn-primary' : 'btn-outline-primary', 'btn-sm', 'my-1']"
|
|
@click="selectedPronoun = pronoun.clone(true)"
|
|
>
|
|
<Spelling :text="pronoun.name(glue)" />
|
|
</button>
|
|
</li>
|
|
</template>
|
|
</ul>
|
|
</li>
|
|
</template>
|
|
</ul>
|
|
</div>
|
|
<div class="alert alert-primary">
|
|
<p class="h3 mb-0 text-center">
|
|
<Spelling escape :text="selectedPronoun.name(glue)" />
|
|
<template v-if="config.pronouns.generator.description ?? true">
|
|
<br>
|
|
<input
|
|
v-model="selectedPronoun.description"
|
|
class="form-control form-input p-0 form-control-sm"
|
|
:size="selectedPronoun.description.length ? selectedPronoun.description.length + 3 : 16"
|
|
:maxlength="Pronoun.DESCRIPTION_MAXLENGTH"
|
|
:placeholder="$t('profile.description')"
|
|
>
|
|
</template>
|
|
</p>
|
|
</div>
|
|
<p>
|
|
<T>pronouns.examples.header</T><T>quotation.colon</T>
|
|
</p>
|
|
<template
|
|
v-for="{ examples: examplesOfHonorific, isHonorific } in examplesByHonorific"
|
|
:key="isHonorific"
|
|
>
|
|
<ul>
|
|
<li v-for="(pronounExample, i) in examplesOfHonorific" :key="i">
|
|
<template v-for="(part, j) in pronounExample.example(selectedPronoun).parts" :key="j">
|
|
<span v-if="typeof part === 'string'"><Spelling :text="part" /></span>
|
|
<input
|
|
v-else-if="part.type === 'morpheme'"
|
|
v-model="selectedPronoun.morphemes[part.morpheme]"
|
|
:class="['form-control form-input p-0', { active: selectedMorpheme === part.morpheme }]"
|
|
:size="selectedPronoun.morphemes[part.morpheme]?.length ?? 0"
|
|
maxlength="24"
|
|
@focus="selectedMorpheme = part.morpheme"
|
|
@blur="selectedMorpheme = ''"
|
|
>
|
|
</template>
|
|
</li>
|
|
</ul>
|
|
<div v-if="config.pronouns.plurals" class="my-3">
|
|
<div v-if="isHonorific" class="custom-control custom-switch">
|
|
<input
|
|
id="pluralHonorific"
|
|
v-model="selectedPronoun.pluralHonorific[0]"
|
|
type="checkbox"
|
|
class="custom-control-input"
|
|
>
|
|
<label class="custom-control-label" for="pluralHonorific">
|
|
<T>pronouns.plural</T>
|
|
<Icon v="level-up" />
|
|
</label>
|
|
</div>
|
|
<div v-else class="custom-control custom-switch">
|
|
<input
|
|
id="plural"
|
|
v-model="selectedPronoun.plural[0]"
|
|
type="checkbox"
|
|
class="custom-control-input"
|
|
>
|
|
<label class="custom-control-label" for="plural">
|
|
<T>pronouns.plural</T>
|
|
<Icon v="level-up" />
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<p class="small">
|
|
<T icon="info-circle">home.generator.alt</T>
|
|
</p>
|
|
<!-- TODO #136
|
|
<p class="small" v-if="config.pronunciation.enabled && $te('home.generator.pronunciation')">
|
|
<Icon v="info-circle"/>
|
|
<T>home.generator.pronunciation</T>
|
|
</p>
|
|
-->
|
|
</PronounsGenerator>
|
|
</template>
|