edit button with validator and YAML
This commit is contained in:
1 parent
ee87eeb616
commit
72cd3bcd09
8 files changed
+68
-35
No files matched your search
Vendored
+2
-1
@@ -29,5 +29,6 @@
|
|||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"editor.maxTokenizationLineLength": 2500
|
"editor.maxTokenizationLineLength": 2500
|
||||||
}
|
},
|
||||||
|
"vue3snippets.enable-compile-vue-file-on-did-save-code": false
|
||||||
}
|
}
|
||||||
@@ -15,15 +15,7 @@
|
|||||||
import { useTemplateRef } from "vue";
|
import { useTemplateRef } from "vue";
|
||||||
import TTS from "./TTS.vue";
|
import TTS from "./TTS.vue";
|
||||||
import AudioButton from "./AudioButton.vue";
|
import AudioButton from "./AudioButton.vue";
|
||||||
|
import { IVoc } from "../types.ts";
|
||||||
export interface IVoc {
|
|
||||||
ko: string;
|
|
||||||
audio?: string;
|
|
||||||
en: string;
|
|
||||||
usages?: IVoc[];
|
|
||||||
notes?: string;
|
|
||||||
examples?: IVoc[];
|
|
||||||
}
|
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
v: IVoc;
|
v: IVoc;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
<nav>
|
<nav>
|
||||||
<label v-for="c in vCats" :key="c">
|
<label v-for="c in vCats" :key="c">
|
||||||
<input type="checkbox" :name="c" checked @change="updateCats(c)" />
|
<input type="checkbox" :name="c" checked @change="updateCats(c)" />
|
||||||
{{ c.replace("_", " ") }}
|
{{ c.replace(/_/g, " ") }}
|
||||||
</label>
|
</label>
|
||||||
</nav>
|
</nav>
|
||||||
<nav>
|
<nav>
|
||||||
@@ -99,8 +99,10 @@ import {
|
|||||||
useTemplateRef,
|
useTemplateRef,
|
||||||
watch,
|
watch,
|
||||||
} from "vue";
|
} from "vue";
|
||||||
import SentenceAudio, { IVoc } from "./SentenceAudio.vue";
|
import yaml from "yaml";
|
||||||
|
import SentenceAudio from "./SentenceAudio.vue";
|
||||||
import { supabase } from "../supabase.ts";
|
import { supabase } from "../supabase.ts";
|
||||||
|
import { IVoc, Voc } from "../types.ts";
|
||||||
|
|
||||||
const { fmKey = "vocabulary" } = defineProps<{
|
const { fmKey = "vocabulary" } = defineProps<{
|
||||||
fmKey?: string;
|
fmKey?: string;
|
||||||
@@ -157,7 +159,7 @@ watch(isKoFirst, () => {
|
|||||||
watch(isEdit, () => {
|
watch(isEdit, () => {
|
||||||
if (isEdit.value) {
|
if (isEdit.value) {
|
||||||
const { ko, ...vContent } = v.value;
|
const { ko, ...vContent } = v.value;
|
||||||
vEditContent.value = JSON.stringify(vContent, null, 2);
|
vEditContent.value = yaml.stringify(vContent);
|
||||||
} else {
|
} else {
|
||||||
vEditContent.value = "";
|
vEditContent.value = "";
|
||||||
}
|
}
|
||||||
@@ -240,7 +242,7 @@ function updateCats(cat: string) {
|
|||||||
|
|
||||||
async function onVContentSave() {
|
async function onVContentSave() {
|
||||||
const oldV = v.value;
|
const oldV = v.value;
|
||||||
const newV = { ko: oldV.ko, ...JSON.parse(vEditContent.value) };
|
const newV = Voc.parse({ ko: oldV.ko, ...yaml.parse(vEditContent.value) });
|
||||||
|
|
||||||
let key = "";
|
let key = "";
|
||||||
let vKey = oldV.ko;
|
let vKey = oldV.ko;
|
||||||
@@ -257,7 +259,8 @@ async function onVContentSave() {
|
|||||||
vCount.set(v.ko, i + 1);
|
vCount.set(v.ko, i + 1);
|
||||||
|
|
||||||
if (oldV.ko === v.ko && oldV.en === v.en) {
|
if (oldV.ko === v.ko && oldV.en === v.en) {
|
||||||
key = k;
|
// TODO: handling multiple fmKey comma-separated
|
||||||
|
key = JSON.stringify([fmKey, k]);
|
||||||
vKey = vK;
|
vKey = vK;
|
||||||
|
|
||||||
vocabulary[k][i_vs] = newV;
|
vocabulary[k][i_vs] = newV;
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import * as z from "zod";
|
||||||
|
|
||||||
|
export const Voc = z.object({
|
||||||
|
ko: z.string(),
|
||||||
|
audio: z.string().optional(),
|
||||||
|
en: z.string(),
|
||||||
|
get usage() {
|
||||||
|
return z.array(Voc).optional();
|
||||||
|
},
|
||||||
|
notes: z.string().optional(),
|
||||||
|
get examples() {
|
||||||
|
return z.array(Voc).optional();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export type IVoc = z.infer<typeof Voc>;
|
||||||
@@ -420,7 +420,7 @@ vocabulary:
|
|||||||
examples:
|
examples:
|
||||||
- ko: 우리 집은 너무 **멀어요**
|
- ko: 우리 집은 너무 **멀어요**
|
||||||
en: Our home is very **far**
|
en: Our home is very **far**
|
||||||
- ko: 저는 먼 병원에 갔어요
|
- ko: 저는 먼 **병원에** 갔어요
|
||||||
en: I went to a **far away** hospital (a hospital that is **far away**)
|
en: I went to a **far away** hospital (a hospital that is **far away**)
|
||||||
|
|
||||||
- ko: 마르다
|
- ko: 마르다
|
||||||
@@ -440,7 +440,7 @@ vocabulary:
|
|||||||
examples:
|
examples:
|
||||||
- ko: 저와 저의 아버지는 너무 **비슷해요**
|
- ko: 저와 저의 아버지는 너무 **비슷해요**
|
||||||
en: My father and I are very **similar**
|
en: My father and I are very **similar**
|
||||||
- ko: 저는 친구와 비슷해요
|
- ko: 저는 친구와 **비슷해요**
|
||||||
en: I am **similar** to my friend
|
en: I am **similar** to my friend
|
||||||
|
|
||||||
- ko: 싫다
|
- ko: 싫다
|
||||||
@@ -1245,7 +1245,7 @@ Example:
|
|||||||
Example:
|
Example:
|
||||||
|
|
||||||
- ⁠<TTS class="md">우리 집은 너무 **멀어요**</TTS> = <span class="md spoiler">Our home is very **far**</span>
|
- ⁠<TTS class="md">우리 집은 너무 **멀어요**</TTS> = <span class="md spoiler">Our home is very **far**</span>
|
||||||
- ⁠<TTS class="md">저는 먼 병원에 갔어요</TTS> = <span class="md spoiler">I went to a **far away** hospital (a hospital that is **far away**)</span>
|
- ⁠<TTS class="md">저는 먼 **병원에** 갔어요</TTS> = <span class="md spoiler">I went to a **far away** hospital (a hospital that is **far away**)</span>
|
||||||
|
|
||||||
</Details>
|
</Details>
|
||||||
|
|
||||||
@@ -1274,7 +1274,7 @@ The pronunciation of this word is closer to “비스타다”
|
|||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
- ⁠<TTS class="md">저와 저의 아버지는 너무 **비슷해요**</TTS> = <span class="md spoiler">My father and I are very **similar**</span>
|
- ⁠<TTS class="md">저와 저의 아버지는 너무 **비슷해요**</TTS> = <span class="md spoiler">My father and I are very **similar**</span>
|
||||||
- ⁠<TTS class="md">저는 친구와 비슷해요</TTS> = <span class="md spoiler">I am **similar** to my friend</span>
|
- ⁠<TTS class="md">저는 친구와 **비슷해요**</TTS> = <span class="md spoiler">I am **similar** to my friend</span>
|
||||||
|
|
||||||
</Details>
|
</Details>
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ vocabulary:
|
|||||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2015/11/Lesson13v6.mp3
|
audio: https://www.howtostudykorean.com/wp-content/uploads/2015/11/Lesson13v6.mp3
|
||||||
en: underground
|
en: underground
|
||||||
examples:
|
examples:
|
||||||
- ko: 차는 지하 **주차장**에 있어요
|
- ko: 차는 **지하** 주차장에 있어요
|
||||||
en: The car is in the **underground** parking lot
|
en: The car is in the **underground** parking lot
|
||||||
|
|
||||||
- ko: 빵
|
- ko: 빵
|
||||||
@@ -80,7 +80,7 @@ vocabulary:
|
|||||||
en: I made **bread** for my friend
|
en: I made **bread** for my friend
|
||||||
- ko: 우리는 **빵**을 같이 먹었어요
|
- ko: 우리는 **빵**을 같이 먹었어요
|
||||||
en: We ate **bread** together
|
en: We ate **bread** together
|
||||||
- ko: 애기는 **밥**하고 빵을 먹었어요
|
- ko: 애기는 밥하고 **빵**을 먹었어요
|
||||||
en: The baby ate rice and **bread**
|
en: The baby ate rice and **bread**
|
||||||
|
|
||||||
- ko: 쓰레기
|
- ko: 쓰레기
|
||||||
@@ -291,7 +291,7 @@ vocabulary:
|
|||||||
examples:
|
examples:
|
||||||
- ko: 우리가 **늦**어서 죄송해요
|
- ko: 우리가 **늦**어서 죄송해요
|
||||||
en: Sorry we arrived **late**
|
en: Sorry we arrived **late**
|
||||||
- ko: 우리는 늦은 저녁을 먹었어요
|
- ko: 우리는 **늦**은 저녁을 먹었어요
|
||||||
en: We ate a **late** dinner
|
en: We ate a **late** dinner
|
||||||
- ko: 그녀는 언제나 **늦**게 와요
|
- ko: 그녀는 언제나 **늦**게 와요
|
||||||
en: She comes **late** every time
|
en: She comes **late** every time
|
||||||
@@ -434,7 +434,7 @@ vocabulary:
|
|||||||
en: I want to eat what we ate **(together)** last time
|
en: I want to eat what we ate **(together)** last time
|
||||||
- ko: 이 일을 **같이** 하고 싶으면 우리는 협조해야 돼요
|
- ko: 이 일을 **같이** 하고 싶으면 우리는 협조해야 돼요
|
||||||
en: If we want to do this job **together**, we have to cooperate
|
en: If we want to do this job **together**, we have to cooperate
|
||||||
- ko: 우리 학교에서 학생들은 역사와 지리를 같이 배워요
|
- ko: 우리 학교에서 학생들은 역사와 지리를 **같이** 배워요
|
||||||
en: At our school, students learn history and geography **together**
|
en: At our school, students learn history and geography **together**
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -571,7 +571,7 @@ Common Usages:
|
|||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
- 차는 지하 **주차장**에 있어요 = <span class="md spoiler">The car is in the **underground** parking lot</span>
|
- 차는 **지하** 주차장에 있어요 = <span class="md spoiler">The car is in the **underground** parking lot</span>
|
||||||
|
|
||||||
</Details>
|
</Details>
|
||||||
|
|
||||||
@@ -589,7 +589,7 @@ Example:
|
|||||||
- 저는 **빵**을 먹고 싶어요 = <span class="md spoiler">I want to eat **bread**</span>
|
- 저는 **빵**을 먹고 싶어요 = <span class="md spoiler">I want to eat **bread**</span>
|
||||||
- 저는 친구를 위해 **빵**을 만들었어요 = <span class="md spoiler">I made **bread** for my friend</span>
|
- 저는 친구를 위해 **빵**을 만들었어요 = <span class="md spoiler">I made **bread** for my friend</span>
|
||||||
- 우리는 **빵**을 같이 먹었어요 = <span class="md spoiler">We ate **bread** together</span>
|
- 우리는 **빵**을 같이 먹었어요 = <span class="md spoiler">We ate **bread** together</span>
|
||||||
- 애기는 **밥**하고 빵을 먹었어요 = <span class="md spoiler">The baby ate rice and **bread**</span>
|
- 애기는 밥하고 **빵**을 먹었어요 = <span class="md spoiler">The baby ate rice and **bread**</span>
|
||||||
|
|
||||||
</Details>
|
</Details>
|
||||||
|
|
||||||
@@ -927,7 +927,7 @@ This is often irrelevant, but 늦다 is both <span class="md spoiler">a verb and
|
|||||||
|
|
||||||
It is often used as an adjective to describe a time that is late. For example:
|
It is often used as an adjective to describe a time that is late. For example:
|
||||||
|
|
||||||
- 우리는 늦은 저녁을 먹었어요 = <span class="md spoiler">We ate a **late** dinner</span>
|
- 우리는 **늦**은 저녁을 먹었어요 = <span class="md spoiler">We ate a **late** dinner</span>
|
||||||
|
|
||||||
As an adjective, ~게 is often added to it in order to create <span class="md spoiler">an adverb</span>. For example:
|
As an adjective, ~게 is often added to it in order to create <span class="md spoiler">an adverb</span>. For example:
|
||||||
|
|
||||||
@@ -1136,7 +1136,7 @@ Examples:
|
|||||||
- 엄마가 우리랑 **같이** 못 먹어서 안타까워요 = <span class="md spoiler">It’s too bad that your mom can’t eat **together** (with us)</span>
|
- 엄마가 우리랑 **같이** 못 먹어서 안타까워요 = <span class="md spoiler">It’s too bad that your mom can’t eat **together** (with us)</span>
|
||||||
- 나는 우리가 지난 번에 **같이** 먹은 것을 먹고 싶어 = <span class="md spoiler">I want to eat what we ate **(together)** last time</span>
|
- 나는 우리가 지난 번에 **같이** 먹은 것을 먹고 싶어 = <span class="md spoiler">I want to eat what we ate **(together)** last time</span>
|
||||||
- 이 일을 **같이** 하고 싶으면 우리는 협조해야 돼요 = <span class="md spoiler">If we want to do this job **together**, we have to cooperate</span>
|
- 이 일을 **같이** 하고 싶으면 우리는 협조해야 돼요 = <span class="md spoiler">If we want to do this job **together**, we have to cooperate</span>
|
||||||
- 우리 학교에서 학생들은 역사와 지리를 같이 배워요 = <span class="md spoiler">At our school, students learn history and geography **together**</span>
|
- 우리 학교에서 학생들은 역사와 지리를 **같이** 배워요 = <span class="md spoiler">At our school, students learn history and geography **together**</span>
|
||||||
|
|
||||||
</Details>
|
</Details>
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -27,6 +27,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@supabase/supabase-js": "^2.110.5",
|
"@supabase/supabase-js": "^2.110.5",
|
||||||
"pdfjs-dist": "^5.7.284",
|
"pdfjs-dist": "^5.7.284",
|
||||||
"tauri-plugin-tts-api": "^0.1.11"
|
"tauri-plugin-tts-api": "^0.1.11",
|
||||||
|
"yaml": "^2.9.0",
|
||||||
|
"zod": "^4.4.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Generated
+26
-7
@@ -17,13 +17,19 @@ importers:
|
|||||||
tauri-plugin-tts-api:
|
tauri-plugin-tts-api:
|
||||||
specifier: ^0.1.11
|
specifier: ^0.1.11
|
||||||
version: 0.1.11
|
version: 0.1.11
|
||||||
|
yaml:
|
||||||
|
specifier: ^2.9.0
|
||||||
|
version: 2.9.0
|
||||||
|
zod:
|
||||||
|
specifier: ^4.4.3
|
||||||
|
version: 4.4.3
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@tauri-apps/cli':
|
'@tauri-apps/cli':
|
||||||
specifier: ^2.11.4
|
specifier: ^2.11.4
|
||||||
version: 2.11.4
|
version: 2.11.4
|
||||||
vitepress:
|
vitepress:
|
||||||
specifier: 2.0.0-alpha.17
|
specifier: 2.0.0-alpha.17
|
||||||
version: 2.0.0-alpha.17(postcss@8.5.16)
|
version: 2.0.0-alpha.17(postcss@8.5.16)(yaml@2.9.0)
|
||||||
vue:
|
vue:
|
||||||
specifier: ^3.5.39
|
specifier: ^3.5.39
|
||||||
version: 3.5.39
|
version: 3.5.39
|
||||||
@@ -950,6 +956,14 @@ packages:
|
|||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
yaml@2.9.0:
|
||||||
|
resolution: {integrity: sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==}
|
||||||
|
engines: {node: '>= 14.6'}
|
||||||
|
hasBin: true
|
||||||
|
|
||||||
|
zod@4.4.3:
|
||||||
|
resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==}
|
||||||
|
|
||||||
zwitch@2.0.4:
|
zwitch@2.0.4:
|
||||||
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
|
||||||
|
|
||||||
@@ -1329,10 +1343,10 @@ snapshots:
|
|||||||
|
|
||||||
'@ungap/structured-clone@1.3.2': {}
|
'@ungap/structured-clone@1.3.2': {}
|
||||||
|
|
||||||
'@vitejs/plugin-vue@6.0.7(vite@7.3.6)(vue@3.5.39)':
|
'@vitejs/plugin-vue@6.0.7(vite@7.3.6(yaml@2.9.0))(vue@3.5.39)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rolldown/pluginutils': 1.0.1
|
'@rolldown/pluginutils': 1.0.1
|
||||||
vite: 7.3.6
|
vite: 7.3.6(yaml@2.9.0)
|
||||||
vue: 3.5.39
|
vue: 3.5.39
|
||||||
|
|
||||||
'@vue/compiler-core@3.5.39':
|
'@vue/compiler-core@3.5.39':
|
||||||
@@ -1683,7 +1697,7 @@ snapshots:
|
|||||||
'@types/unist': 3.0.3
|
'@types/unist': 3.0.3
|
||||||
vfile-message: 4.0.3
|
vfile-message: 4.0.3
|
||||||
|
|
||||||
vite@7.3.6:
|
vite@7.3.6(yaml@2.9.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.28.1
|
esbuild: 0.28.1
|
||||||
fdir: 6.5.0(picomatch@4.0.5)
|
fdir: 6.5.0(picomatch@4.0.5)
|
||||||
@@ -1693,8 +1707,9 @@ snapshots:
|
|||||||
tinyglobby: 0.2.17
|
tinyglobby: 0.2.17
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents: 2.3.3
|
fsevents: 2.3.3
|
||||||
|
yaml: 2.9.0
|
||||||
|
|
||||||
vitepress@2.0.0-alpha.17(postcss@8.5.16):
|
vitepress@2.0.0-alpha.17(postcss@8.5.16)(yaml@2.9.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@docsearch/css': 4.6.3
|
'@docsearch/css': 4.6.3
|
||||||
'@docsearch/js': 4.6.3
|
'@docsearch/js': 4.6.3
|
||||||
@@ -1704,7 +1719,7 @@ snapshots:
|
|||||||
'@shikijs/transformers': 3.23.0
|
'@shikijs/transformers': 3.23.0
|
||||||
'@shikijs/types': 3.23.0
|
'@shikijs/types': 3.23.0
|
||||||
'@types/markdown-it': 14.1.2
|
'@types/markdown-it': 14.1.2
|
||||||
'@vitejs/plugin-vue': 6.0.7(vite@7.3.6)(vue@3.5.39)
|
'@vitejs/plugin-vue': 6.0.7(vite@7.3.6(yaml@2.9.0))(vue@3.5.39)
|
||||||
'@vue/devtools-api': 8.1.5
|
'@vue/devtools-api': 8.1.5
|
||||||
'@vue/shared': 3.5.39
|
'@vue/shared': 3.5.39
|
||||||
'@vueuse/core': 14.3.0(vue@3.5.39)
|
'@vueuse/core': 14.3.0(vue@3.5.39)
|
||||||
@@ -1713,7 +1728,7 @@ snapshots:
|
|||||||
mark.js: 8.11.1
|
mark.js: 8.11.1
|
||||||
minisearch: 7.2.0
|
minisearch: 7.2.0
|
||||||
shiki: 3.23.0
|
shiki: 3.23.0
|
||||||
vite: 7.3.6
|
vite: 7.3.6(yaml@2.9.0)
|
||||||
vue: 3.5.39
|
vue: 3.5.39
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
postcss: 8.5.16
|
postcss: 8.5.16
|
||||||
@@ -1750,4 +1765,8 @@ snapshots:
|
|||||||
'@vue/server-renderer': 3.5.39(vue@3.5.39)
|
'@vue/server-renderer': 3.5.39(vue@3.5.39)
|
||||||
'@vue/shared': 3.5.39
|
'@vue/shared': 3.5.39
|
||||||
|
|
||||||
|
yaml@2.9.0: {}
|
||||||
|
|
||||||
|
zod@4.4.3: {}
|
||||||
|
|
||||||
zwitch@2.0.4: {}
|
zwitch@2.0.4: {}
|
||||||
Reference in new issue
Block a user