vocab quiz convert ** to em

This commit is contained in:
polv committed 2026-07-07 17:34:54 +07:00
1 parent cfa93c6e12
commit dd2708f905
3 files changed
+75 -34

No files matched your search

@@ -13,9 +13,13 @@ const props = defineProps<{
src: string; src: string;
}>(); }>();
defineExpose({
playAudio,
});
const audioEl = useTemplateRef("audio"); const audioEl = useTemplateRef("audio");
function playAudio() { async function playAudio() {
if (!audioEl.value) return; if (!audioEl.value) return;
document.querySelectorAll("audio").forEach((el) => { document.querySelectorAll("audio").forEach((el) => {
@@ -25,7 +29,7 @@ function playAudio() {
audioEl.value.src = props.src; audioEl.value.src = props.src;
audioEl.value.currentTime = 0; audioEl.value.currentTime = 0;
audioEl.value.play(); await audioEl.value.play();
} }
</script> </script>
@@ -0,0 +1,54 @@
<template>
<component :is="lang !== 'ko' || v.audio ? 'span' : TTS" ref="stts">
<span
v-for="(seg, i) in v[lang].split('**')"
:key="i"
:class="i % 2 === 0 ? '' : spoiler ? 'spoiler' : $style.em"
>
{{ seg }}
</span>
<AudioButton v-if="lang === 'ko' && v.audio" :src="v.audio" ref="saud" />
</component>
</template>
<script setup lang="ts">
import { useTemplateRef } from "vue";
import TTS from "./TTS.vue";
import AudioButton from "./AudioButton.vue";
export interface IVoc {
ko: string;
audio?: string;
en: string;
usages?: IVoc[];
notes?: string;
examples?: IVoc[];
}
defineProps<{
v: IVoc;
lang: "ko" | "en";
spoiler?: boolean;
}>();
defineExpose({
playAudio,
});
const stts = useTemplateRef<HTMLSpanElement | InstanceType<typeof TTS>>("stts");
const saud = useTemplateRef<InstanceType<typeof AudioButton>>("saud");
async function playAudio() {
if (saud.value) {
await saud.value.playAudio();
} else if (stts.value && "playAudio" in stts.value) {
await stts.value.playAudio();
}
}
</script>
<style module>
.em {
font-style: italic;
}
</style>
+15 -32
View File
@@ -15,30 +15,22 @@
<div> <div>
<span :class="isKoFirst ? '' : 'spoiler'"> <span :class="isKoFirst ? '' : 'spoiler'">
<span v-if="v.audio"> <SentenceAudio :v="v" lang="ko" />
{{ v.ko }}
<AudioButton :src="v.audio" />
</span>
<TTS v-else>
{{ v.ko }}
</TTS>
</span> </span>
<span>{{ " = " }}</span> <span>{{ " = " }}</span>
<span :class="isKoFirst ? 'spoiler' : ''"> {{ v.en }} </span> <span :class="isKoFirst ? 'spoiler' : ''"> {{ v.en }} </span>
</div> </div>
<details v-if="example" ref="sdetails"> <details v-if="example" ref="sdetails">
<summary :class="isKoFirst ? '' : 'spoiler'"> <summary>
<span v-if="example.audio"> <SentenceAudio
{{ example.ko }} :v="example"
<AudioButton :src="example.audio" /> lang="ko"
</span> :spoiler="!isKoFirst"
<TTS v-else ref="stts"> ref="saud"
{{ example.ko }} />
</TTS>
</summary> </summary>
<span>{{ example.en }}</span> <SentenceAudio :v="example" lang="en" />
<blockquote <blockquote
v-if="v.notes" v-if="v.notes"
v-html="v.notes" v-html="v.notes"
@@ -85,7 +77,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { useData } from "vitepress"; import { useData } from "vitepress";
import { computed, nextTick, ref, useTemplateRef, watch } from "vue"; import { computed, nextTick, ref, useTemplateRef, watch } from "vue";
import TTS from "./TTS.vue"; import SentenceAudio, { IVoc } from "./SentenceAudio.vue";
const vCats = ref<string[]>([]); const vCats = ref<string[]>([]);
const vChosenCats = ref<string[]>([]); const vChosenCats = ref<string[]>([]);
@@ -96,7 +88,7 @@ const isSentAutoplayAudio = ref(true);
const isKoFirst = ref(true); const isKoFirst = ref(true);
const sentenceDetails = useTemplateRef("sdetails"); const sentenceDetails = useTemplateRef("sdetails");
const stts = useTemplateRef<InstanceType<typeof TTS>>("stts"); const saud = useTemplateRef<InstanceType<typeof SentenceAudio>>("saud");
const v = computed(() => vList.value[vIndex.value]); const v = computed(() => vList.value[vIndex.value]);
const example = computed(() => { const example = computed(() => {
@@ -107,15 +99,6 @@ const example = computed(() => {
const MAX_VOC = 5; const MAX_VOC = 5;
interface IVoc {
ko: string;
audio?: string;
en: string;
usages?: IVoc[];
notes?: string;
examples?: IVoc[];
}
const { frontmatter } = useData(); const { frontmatter } = useData();
const { vocabulary } = frontmatter.value as { const { vocabulary } = frontmatter.value as {
vocabulary: Record<string, IVoc[]>; vocabulary: Record<string, IVoc[]>;
@@ -156,11 +139,11 @@ function mark(isRight: boolean) {
} }
if (isSentAutoplayAudio.value) { if (isSentAutoplayAudio.value) {
if (stts.value) { nextTick(() => {
stts.value.playAudio(); if (saud.value) {
} else if (example.value?.audio) { saud.value.playAudio();
new Audio(example.value.audio).play();
} }
});
} }
}); });