From 4317c65c458f615495fe681d71d1b6582cebf6e5 Mon Sep 17 00:00:00 2001 From: Philipp Stadler <a51820432@unet.univie.ac.at> Date: Mon, 15 Jul 2024 11:04:31 +0000 Subject: [PATCH] ci: add automatic releases --- .gitignore | 4 +- .gitlab-ci.yml | 8 +- src/templates/bijective/.template-spec.yaml | 16 + src/templates/bijective/backward/back.html | 23 ++ src/templates/bijective/backward/front.html | 29 ++ src/templates/bijective/forward/back.html | 23 ++ src/templates/bijective/forward/front.html | 29 ++ src/templates/facts/.template-spec.yaml | 14 + src/templates/facts/q_a/back.html | 23 ++ src/templates/facts/q_a/front.html | 29 ++ src/templates/hanzi/.template-spec.yaml | 26 ++ src/templates/hanzi/write/back.html | 28 ++ src/templates/hanzi/write/front.html | 36 ++ src/templates/index.html | 90 +++++ src/templates/molaoshi/.template-spec.yaml | 45 +++ src/templates/molaoshi/hear/back.html | 68 ++++ src/templates/molaoshi/hear/front.html | 45 +++ .../molaoshi/identify_radical/back.html | 35 ++ .../molaoshi/identify_radical/front.html | 39 ++ .../identify_radical_traditional/back.html | 35 ++ .../identify_radical_traditional/front.html | 39 ++ src/templates/molaoshi/read_hanzi/back.html | 76 ++++ src/templates/molaoshi/read_hanzi/front.html | 39 ++ .../molaoshi/read_hanzi_traditional/back.html | 76 ++++ .../read_hanzi_traditional/front.html | 39 ++ src/templates/molaoshi/read_pinyin/back.html | 81 +++++ src/templates/molaoshi/read_pinyin/front.html | 34 ++ src/templates/molaoshi/speak/back.html | 81 +++++ src/templates/molaoshi/speak/front.html | 34 ++ src/templates/molaoshi/write/back.html | 81 +++++ src/templates/molaoshi/write/front.html | 34 ++ test/build/fixtures/anki/.apkg-spec.yaml | 8 - test/build/fixtures/anki/Test.apkg | Bin 55648 -> 0 bytes test/build/fixtures/csv/.apkg-spec.yaml | 18 - test/build/fixtures/csv/content.csv | 1 - .../csv_updated_content/.apkg-spec.yaml | 18 - .../fixtures/csv_updated_content/content.csv | 1 - .../templates_updated/q_a/.template-spec.yaml | 14 - .../templates_updated/q_a/q_a/back.html | 1 - .../templates_updated/q_a/q_a/front.html | 1 - test/build/test_export_apkgs.py | 337 ------------------ test/templates/hanzi-data.test.ts | 202 +++++++++++ test/templates/is-hanzi.test.ts | 29 ++ test/templates/lut.test.ts | 41 +++ 44 files changed, 1526 insertions(+), 404 deletions(-) create mode 100644 src/templates/bijective/.template-spec.yaml create mode 100644 src/templates/bijective/backward/back.html create mode 100644 src/templates/bijective/backward/front.html create mode 100644 src/templates/bijective/forward/back.html create mode 100644 src/templates/bijective/forward/front.html create mode 100644 src/templates/facts/.template-spec.yaml create mode 100644 src/templates/facts/q_a/back.html create mode 100644 src/templates/facts/q_a/front.html create mode 100644 src/templates/hanzi/.template-spec.yaml create mode 100644 src/templates/hanzi/write/back.html create mode 100644 src/templates/hanzi/write/front.html create mode 100644 src/templates/index.html create mode 100644 src/templates/molaoshi/.template-spec.yaml create mode 100644 src/templates/molaoshi/hear/back.html create mode 100644 src/templates/molaoshi/hear/front.html create mode 100644 src/templates/molaoshi/identify_radical/back.html create mode 100644 src/templates/molaoshi/identify_radical/front.html create mode 100644 src/templates/molaoshi/identify_radical_traditional/back.html create mode 100644 src/templates/molaoshi/identify_radical_traditional/front.html create mode 100644 src/templates/molaoshi/read_hanzi/back.html create mode 100644 src/templates/molaoshi/read_hanzi/front.html create mode 100644 src/templates/molaoshi/read_hanzi_traditional/back.html create mode 100644 src/templates/molaoshi/read_hanzi_traditional/front.html create mode 100644 src/templates/molaoshi/read_pinyin/back.html create mode 100644 src/templates/molaoshi/read_pinyin/front.html create mode 100644 src/templates/molaoshi/speak/back.html create mode 100644 src/templates/molaoshi/speak/front.html create mode 100644 src/templates/molaoshi/write/back.html create mode 100644 src/templates/molaoshi/write/front.html delete mode 100644 test/build/fixtures/anki/.apkg-spec.yaml delete mode 100644 test/build/fixtures/anki/Test.apkg delete mode 100644 test/build/fixtures/csv/.apkg-spec.yaml delete mode 100644 test/build/fixtures/csv/content.csv delete mode 100644 test/build/fixtures/csv_updated_content/.apkg-spec.yaml delete mode 100644 test/build/fixtures/csv_updated_content/content.csv delete mode 100644 test/build/fixtures/templates_updated/q_a/.template-spec.yaml delete mode 100644 test/build/fixtures/templates_updated/q_a/q_a/back.html delete mode 100644 test/build/fixtures/templates_updated/q_a/q_a/front.html delete mode 100644 test/build/test_export_apkgs.py create mode 100644 test/templates/hanzi-data.test.ts create mode 100644 test/templates/is-hanzi.test.ts create mode 100644 test/templates/lut.test.ts diff --git a/.gitignore b/.gitignore index 8edad87..406c7f3 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,9 @@ __pycache__ .vscode .build-cache .venv -artifacts +/artifacts *.d.mk -templates +/templates /*.apkg hanzi-data .data-test-ok diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6865d46..4e3030b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -27,8 +27,7 @@ build: - echo RELEASE_TAR_URL=$RELEASE_TAR_URL >> build.env artifacts: paths: - - sinologie-anki-pack-* - - ANNOUNCEMENT + - card-templates-*.tar.gz reports: dotenv: build.env @@ -48,7 +47,7 @@ release-package-json-version-as-git-tag: - if [ -z "$NPM_VERSION_GIT_TAG" ]; then - echo adding git tag for first commit on main with NPM version ${NPM_VERSION} - git remote remove origin - - git remote add origin https://oauth:${REPOSITORY_ACCESS_TOKEN}@gitlab.phaidra.org/kartenaale/sinologie-anki-pack.git + - git remote add origin https://oauth:${REPOSITORY_ACCESS_TOKEN}@gitlab.phaidra.org/kartenaale/card-templates.git - git config user.email Cao Cao - git config user.name cao.cao@ci.kartenaale - git tag -a $NPM_VERSION -m "Release $NPM_VERSION" @@ -70,9 +69,12 @@ create-gitlab-release: GIT_STRATEGY: none # we don't need anything in node_modules or python, so don't fetch the cache cache: [] + script: + - echo Creating GitLab release… release: tag_name: '$CI_COMMIT_TAG' name: 'Card Templates $CI_COMMIT_TAG' + description: '$RELEASE_TAR is ready for download.' assets: links: - name: '$RELEASE_TAR' diff --git a/src/templates/bijective/.template-spec.yaml b/src/templates/bijective/.template-spec.yaml new file mode 100644 index 0000000..ed45670 --- /dev/null +++ b/src/templates/bijective/.template-spec.yaml @@ -0,0 +1,16 @@ +template_version: 2024-02-28 22:00:00+00:00 + +note_type: + id: 2024-01-05 03:00:00+00:00 + name: Bijection + fields: + - A + - B + +card_types: +- name: Forward + template: forward +- name: Backward + template: backward + +resource_paths: [] diff --git a/src/templates/bijective/backward/back.html b/src/templates/bijective/backward/back.html new file mode 100644 index 0000000..84534fb --- /dev/null +++ b/src/templates/bijective/backward/back.html @@ -0,0 +1,23 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back bijective-backward-back"> + <div class="bijective-answer"> + {{A}} + </div> + + <include src="src/components/notice/notice.html"></include> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/bijective/backward/front.html b/src/templates/bijective/backward/front.html new file mode 100644 index 0000000..8fb070c --- /dev/null +++ b/src/templates/bijective/backward/front.html @@ -0,0 +1,29 @@ +<style> + @import url(../../../components/global.css); + @import url(../../../components/facts.css); +</style> + +<div class="exercise front bijective-backward-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + + <div class="prompt bijective-question"> + {{B}} + </div> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> \ No newline at end of file diff --git a/src/templates/bijective/forward/back.html b/src/templates/bijective/forward/back.html new file mode 100644 index 0000000..afbae1a --- /dev/null +++ b/src/templates/bijective/forward/back.html @@ -0,0 +1,23 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back bijective-forward-back"> + <div class="bijective-answer"> + {{B}} + </div> + + <include src="src/components/notice/notice.html"></include> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/bijective/forward/front.html b/src/templates/bijective/forward/front.html new file mode 100644 index 0000000..6552410 --- /dev/null +++ b/src/templates/bijective/forward/front.html @@ -0,0 +1,29 @@ +<style> + @import url(../../../components/global.css); + @import url(../../../components/facts.css); +</style> + +<div class="exercise front bijective-forward-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + + <div class="prompt bijective-question"> + {{A}} + </div> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> \ No newline at end of file diff --git a/src/templates/facts/.template-spec.yaml b/src/templates/facts/.template-spec.yaml new file mode 100644 index 0000000..fe384c1 --- /dev/null +++ b/src/templates/facts/.template-spec.yaml @@ -0,0 +1,14 @@ +template_version: 2024-02-28 22:00:00+00:00 + +note_type: + id: 2024-01-04 03:00:00+00:00 + name: Facts + fields: + - Front + - Back + +card_types: +- name: Q/A + template: q_a + +resource_paths: [] diff --git a/src/templates/facts/q_a/back.html b/src/templates/facts/q_a/back.html new file mode 100644 index 0000000..1ac8a07 --- /dev/null +++ b/src/templates/facts/q_a/back.html @@ -0,0 +1,23 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back facts-q-a-back"> + <div class="facts-answer"> + {{Back}} + </div> + + <include src="src/components/notice/notice.html"></include> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/facts/q_a/front.html b/src/templates/facts/q_a/front.html new file mode 100644 index 0000000..9dce46e --- /dev/null +++ b/src/templates/facts/q_a/front.html @@ -0,0 +1,29 @@ +<style> + @import url(../../../components/global.css); + @import url(../../../components/facts.css); +</style> + +<div class="exercise front facts-q-a-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + + <div class="prompt facts-question"> + {{Front}} + </div> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> \ No newline at end of file diff --git a/src/templates/hanzi/.template-spec.yaml b/src/templates/hanzi/.template-spec.yaml new file mode 100644 index 0000000..0908f30 --- /dev/null +++ b/src/templates/hanzi/.template-spec.yaml @@ -0,0 +1,26 @@ +template_version: 2024-03-20 10:00:00+00:00 + +note_type: + id: 2024-02-21 12:00:00+00:00 + name: Hanzi + fields: + - Keyword + - Keyword type + - Notes (Front) + - Hanzi + - Book + - Lesson + - Frame + - Order (Sequential) + - Order (Parallel) + - resources + - Notes (Back) + - Traditional + - Simplified + +card_types: +- name: Schreiben + template: write + +resource_paths: +- '{{BUILD_PREFIX}}hanzi-data' diff --git a/src/templates/hanzi/write/back.html b/src/templates/hanzi/write/back.html new file mode 100644 index 0000000..b176010 --- /dev/null +++ b/src/templates/hanzi/write/back.html @@ -0,0 +1,28 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back hanzi-write-back"> + <dl class="translations"> + <dt>Stroke order</dt> + <dd class="strichfolge-animation is-large{{#Traditional}} is-traditional{{/Traditional}}">{{text:Hanzi}}</dd> + <dt>Notes</dt> + <dd>{{Notes (Back)}}</dd> + <dt>Print form</dt> + <dd><span class="hanzi-print is-large">{{Hanzi}}</span></dd> + </dl> + + <include src="src/components/notice/notice.html"></include> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/hanzi/write/front.html b/src/templates/hanzi/write/front.html new file mode 100644 index 0000000..f58e910 --- /dev/null +++ b/src/templates/hanzi/write/front.html @@ -0,0 +1,36 @@ +{{#Hanzi}}{{#Keyword}} +<style> + @import url(../../../components/global.css); + @import url(../../../components/heisig.css); +</style> + +<div class="exercise front hanzi-write-front"> + <header class="card-info"> + <aside class="exercise-kind"> + {{Frame}} + </aside> + </header> + + <dl class="prompt translations"> + <dt>Key word</dt> + <dd> + <span class="hanzi-keyword">{{Keyword}}</span> + {{#Keyword type}} + <span class="hanzi-keyword-type">({{Keyword type}})</span> + {{/Keyword type}} + </dd> + <dt>Notes</dt> + <dd>{{Notes (Front)}}</dd> + </dl> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> +{{/Keyword}}{{/Hanzi}} \ No newline at end of file diff --git a/src/templates/index.html b/src/templates/index.html new file mode 100644 index 0000000..700a612 --- /dev/null +++ b/src/templates/index.html @@ -0,0 +1,90 @@ +<!DOCTYPE html> +<html lang="en"> + +<head> + <meta charset="UTF-8"> + <meta http-equiv="X-UA-Compatible" content="IE=edge"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>Anki Template Hanyu Overview</title> +</head> + +<body> + <h1>Overview</h1> + + <h2>templates/bijective</h2> + <h3>Forward</h3> + <h4>Front</h4> + <a href="bijective/backward/front.html">forward/front.html</a> + <h4>Back</h4> + <a href="bijective/backward/back.html">forward/back.html</a> + <h3>Backward</h3> + <h4>Front</h4> + <a href="bijective/forward/front.html">backward/front.html</a> + <h4>Back</h4> + <a href="bijective/forward/back.html">backward/back.html</a> + + <h2>templates/facts</h2> + <h3>Q/A</h3> + <h4>Front</h4> + <a href="facts/q_a/front.html">q_a/front.html</a> + <h4>Back</h4> + <a href="facts/q_a/back.html"> q_a/back.html</a> + + <h2>templates/hanzi</h2> + <h3>Write</h3> + <h4>Front</h4> + <a href="hanzi/write/front.html">write/front.html</a> + <h4>Back</h4> + <a href="hanzi/write/back.html">write/back.html</a> + + <h2>templates/molaoshi</h2> + <h3>Hear</h3> + <h4>Front</h4> + <a href="molaoshi/hear/front.html">hear/front.html</a> + <h4>Back</h4> + <a href="molaoshi/hear/back.html">hear/back.html</a> + + <h3>Read Hanzi</h3> + <h4>Front</h4> + <a href="molaoshi/read_hanzi/front.html">read_hanzi/front.html</a> + <h4>Back</h4> + <a href="molaoshi/read_hanzi/back.html">read_hanzi/back.html</a> + + <h3>Read Hanzi (traditional)</h3> + <h4>Front</h4> + <a href="molaoshi/read_hanzi_traditional/front.html">read_hanzi_traditional/front.html</a> + <h4>Back</h4> + <a href="molaoshi/read_hanzi_traditional/back.html">read_hanzi_traditional/back.html</a> + + <h3>Read Pinyin</h3> + <h4>Front</h4> + <a href="molaoshi/read_pinyin/front.html">read_pinyin/front.html</a> + <h4>Back</h4> + <a href="molaoshi/read_pinyin/back.html">read_pinyin/back.html</a> + + <h3>Speak</h3> + <h4>Front</h4> + <a href="molaoshi/speak/front.html">speak/front.html</a> + <h4>Back</h4> + <a href="molaoshi/speak/back.html">speak/back.html</a> + + <h3>Write</h3> + <h4>Front</h4> + <a href="molaoshi/write/front.html">write/front.html</a> + <h4>Back</h4> + <a href="molaoshi/write/back.html">write/back.html</a> + + <h3>Identify radical</h3> + <h4>Front</h4> + <a href="molaoshi/identify_radical/front.html">identify_radical/front.html</a> + <h4>Back</h4> + <a href="molaoshi/identify_radical/back.html">identify_radical/back.html</a> + + <h3>Identify radical (traditional)</h3> + <h4>Front</h4> + <a href="molaoshi/identify_radical_traditional/front.html">identify_radical_traditional/front.html</a> + <h4>Back</h4> + <a href="molaoshi/identify_radical_traditional/back.html">identify_radical_traditional/back.html</a> +</body> + +</html> \ No newline at end of file diff --git a/src/templates/molaoshi/.template-spec.yaml b/src/templates/molaoshi/.template-spec.yaml new file mode 100644 index 0000000..5f982c7 --- /dev/null +++ b/src/templates/molaoshi/.template-spec.yaml @@ -0,0 +1,45 @@ +template_version: 2024-06-14 12:00:00+00:00 + +note_type: + id: 2024-02-20 12:00:00+00:00 + name: Vokabeln + fields: + - Deutsch + - 简体字 + - 繁體字 + - Pīnyīn + - Bemerkungen + - Beispiele + - Lektion + # this is only necessary to make explicit to keep the later added fields + # id contents + - resources + - Bemerkungen (Vorderseite) + - Standardaussprache + - Audioaufnahme + - Radikal finden anlegen + - Radikal finden (繁體字) anlegen + - Schreiben anlegen + - Zhuyin + - Lesen (繁體字) anlegen + +card_types: +- name: Hören + template: hear +- name: Lesen (Pīnyīn) + template: read_pinyin +- name: Lesen (简体字) + template: read_hanzi +- name: Lesen (繁體字) + template: read_hanzi_traditional +- name: Schreiben + template: write +- name: Sprechen + template: speak +- name: Radikal finden (简体字) + template: identify_radical +- name: Radikal finden (繁體字) + template: identify_radical_traditional + +resource_paths: +- '{{BUILD_PREFIX}}hanzi-data' diff --git a/src/templates/molaoshi/hear/back.html b/src/templates/molaoshi/hear/back.html new file mode 100644 index 0000000..a32ec6f --- /dev/null +++ b/src/templates/molaoshi/hear/back.html @@ -0,0 +1,68 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back anki-template-hanyu-hear-back"> + <dl class="translations"> + <dt>Pīnyīn</dt> + <dd>{{Pīnyīn}}</dd> + <dt>Deutsch</dt> + <dd>{{Deutsch}}</dd> + <dt>简体字</dt> + <dd> + <span class="hanzi-print">{{简体字}}</span> + <div class="strichfolge-animation" no-animate="true" highlight-radical="true"> + {{text:简体字}} + </div> + </dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen}}</dd> + <dt>Beispiele</dt> + <dd>{{Beispiele}}</dd> + <details class="answer-details"> + <summary> + <span class="answer-details-more">Mehr…</span> + <span class="answer-details-less">Weniger…</span> + </summary> + {{#繁體字}} + <dt>繁體字</dt> + <dd> + <span class="hanzi-print">{{繁體字}}</span> + <div class="strichfolge-animation is-traditional" no-animate="true" highlight-radical="true"> + {{text:繁體字}} + </div> + </dd> + {{/繁體字}} + <dt>Radikal (简体字)</dt> + <dd> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation" no-animate="true"> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical"></span> + </div> + </dd> + {{#繁體字}} + <dt>Radikal (繁體字)</dt> + <dd> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation is-traditional" no-animate="true"> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical"></span> + </div> + </dd> + {{/繁體字}} + </details> + </dl> + + <include src="src/components/notice/notice.html"></include> +</div> + +<!-- Repeat only relevant text on the back side on AnkiDroid, not all of it --> +<tts style="display: none" service="android" voice="zh_CN">{{text:简体字}}</tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/molaoshi/hear/front.html b/src/templates/molaoshi/hear/front.html new file mode 100644 index 0000000..6d7b05d --- /dev/null +++ b/src/templates/molaoshi/hear/front.html @@ -0,0 +1,45 @@ +{{#Standardaussprache}} +<style> + @import url(../../../components/global.css); +</style> + +<div class="exercise front anki-template-hanyu-hear-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + </header> + + <dl class="prompt translations"> + <dt>汉语</dt> + <dd id="t2s-player-container" class="t2s-player-container"> + <div class="anki-droid-player"> + <tts style="display: none" service="android" voice="zh_CN"> + {{text:Standardaussprache}} + </tts> + </div> + <div class="anki-web-player"> + {{text:Standardaussprache}} + </div> + <div class="anki-builtin-player"> + {{tts zh_CN:Standardaussprache}} + </div> + </dd> + <dt>Aufnahme</dt> + <dd>{{Audioaufnahme}}</dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen (Vorderseite)}}</dd> + </dl> +</div> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> +{{/Standardaussprache}} \ No newline at end of file diff --git a/src/templates/molaoshi/identify_radical/back.html b/src/templates/molaoshi/identify_radical/back.html new file mode 100644 index 0000000..0d1a17e --- /dev/null +++ b/src/templates/molaoshi/identify_radical/back.html @@ -0,0 +1,35 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back radicals-identify-back"> + <dl class="translations"> + <dt>Radikal (简体字)</dt> + <dd> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation" no-animate="true"> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical"></span> + </div> + </dd> + <dt>Name (中文)</dt> + <dd hanzi-data="{{text:简体字}}" hanzi-prop="radicalMeaningZh"></dd> + <dt>Name (Deutsch)</dt> + <dd hanzi-data="{{text:简体字}}" hanzi-prop="radicalMeaningDe"></dd> + <dt>Strichzahl</dt> + <dd hanzi-data="{{text:简体字}}" hanzi-prop="count"></dd> + </dl> + + <include src="src/components/notice/notice.html"></include> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/molaoshi/identify_radical/front.html b/src/templates/molaoshi/identify_radical/front.html new file mode 100644 index 0000000..e0302ce --- /dev/null +++ b/src/templates/molaoshi/identify_radical/front.html @@ -0,0 +1,39 @@ +{{#简体字}}{{#Radikal finden anlegen}} +<style> + @import url(../../../components/global.css); +</style> + +<div class="exercise front radicals-identify-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + </header> + + <dl class="prompt translations"> + <dt>简体字</dt> + <dd> + <span class="hanzi-print">{{简体字}}</span> + <div class="strichfolge-animation" no-animate="true" highlight-radical="answer"> + {{text:简体字}} + </div> + </dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen (Vorderseite)}}</dd> + </dl> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> +{{/Radikal finden anlegen}}{{/简体字}} \ No newline at end of file diff --git a/src/templates/molaoshi/identify_radical_traditional/back.html b/src/templates/molaoshi/identify_radical_traditional/back.html new file mode 100644 index 0000000..7a642be --- /dev/null +++ b/src/templates/molaoshi/identify_radical_traditional/back.html @@ -0,0 +1,35 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back radicals-identify-back"> + <dl class="translations"> + <dt>Radikal (繁體字)</dt> + <dd> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation is-traditional" no-animate="true"> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical"></span> + </div> + </dd> + <dt>Name (中文)</dt> + <dd hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radicalMeaningZh"></dd> + <dt>Name (Deutsch)</dt> + <dd hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radicalMeaningDe"></dd> + <dt>Strichzahl</dt> + <dd hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="count"></dd> + </dl> + + <include src="src/components/notice/notice.html"></include> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/molaoshi/identify_radical_traditional/front.html b/src/templates/molaoshi/identify_radical_traditional/front.html new file mode 100644 index 0000000..ea10b1c --- /dev/null +++ b/src/templates/molaoshi/identify_radical_traditional/front.html @@ -0,0 +1,39 @@ +{{#繁體字}}{{#Radikal finden (繁體字) anlegen}} +<style> + @import url(../../../components/global.css); +</style> + +<div class="exercise front radicals-identify-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + </header> + + <dl class="prompt translations"> + <dt>繁體字</dt> + <dd> + <span class="hanzi-print">{{繁體字}}</span> + <div class="strichfolge-animation is-traditional" no-animate="true" highlight-radical="answer"> + {{text:繁體字}} + </div> + </dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen (Vorderseite)}}</dd> + </dl> +</div> + +<!-- Suppress speech output on AnkiDroid if globally enabled --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> +{{/Radikal finden (繁體字) anlegen}}{{/繁體字}} \ No newline at end of file diff --git a/src/templates/molaoshi/read_hanzi/back.html b/src/templates/molaoshi/read_hanzi/back.html new file mode 100644 index 0000000..a16bcfd --- /dev/null +++ b/src/templates/molaoshi/read_hanzi/back.html @@ -0,0 +1,76 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back anki-template-hanyu-read-hanzi-back"> + <dl class="translations"> + <dt>Pīnyīn</dt> + <dd>{{Pīnyīn}}</dd> + <dt>Deutsch</dt> + <dd>{{Deutsch}}</dd> + {{#Standardaussprache}} + <dt class="t2s-player-heading">汉语</dt> + <dd id="t2s-player-container" class="t2s-player-container"> + <div class="anki-droid-player"> + <tts style="display: none" service="android" voice="zh_CN"> + {{text:Standardaussprache}} + </tts> + </div> + <div class="anki-web-player"> + {{text:Standardaussprache}} + </div> + <div class="anki-builtin-player"> + {{tts zh_CN:Standardaussprache}} + </div> + </dd> + {{/Standardaussprache}} + <dt>Aufnahme</dt> + <dd>{{Audioaufnahme}}</dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen}}</dd> + <dt>Beispiele</dt> + <dd>{{Beispiele}}</dd> + <details class="answer-details"> + <summary> + <span class="answer-details-more">Mehr…</span> + <span class="answer-details-less">Weniger…</span> + </summary> + {{#繁體字}} + <dt>繁體字</dt> + <dd> + <span class="hanzi-print">{{繁體字}}</span> + <div class="strichfolge-animation is-traditional" no-animate="true" highlight-radical="true"> + {{text:繁體字}} + </div> + </dd> + {{/繁體字}} + <dt>Radikal (简体字)</dt> + <dd> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation" no-animate="true"> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical"></span> + </div> + </dd> + {{#繁體字}} + <dt>Radikal (繁體字)</dt> + <dd> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation is-traditional" no-animate="true"> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical"></span> + </div> + </dd> + {{/繁體字}} + </details> + </dl> + + <include src="src/components/notice/notice.html"></include> +</div> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/molaoshi/read_hanzi/front.html b/src/templates/molaoshi/read_hanzi/front.html new file mode 100644 index 0000000..2238436 --- /dev/null +++ b/src/templates/molaoshi/read_hanzi/front.html @@ -0,0 +1,39 @@ +{{#简体字}} +<style> + @import url(../../../components/global.css); +</style> + +<div class="exercise front anki-template-hanyu-read-hanzi-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + </header> + + <dl class="prompt translations"> + <dt>简体字</dt> + <dd> + <span class="hanzi-print">{{简体字}}</span> + <div class="strichfolge-animation" no-animate="true" highlight-radical="answer"> + {{text:简体字}} + </div> + </dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen (Vorderseite)}}</dd> + </dl> +</div> + +<!-- Suppress speech output on AnkiDroid until card flipped --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> +{{/简体字}} \ No newline at end of file diff --git a/src/templates/molaoshi/read_hanzi_traditional/back.html b/src/templates/molaoshi/read_hanzi_traditional/back.html new file mode 100644 index 0000000..e95f0c0 --- /dev/null +++ b/src/templates/molaoshi/read_hanzi_traditional/back.html @@ -0,0 +1,76 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back anki-template-hanyu-read-hanzi-back"> + <dl class="translations"> + <dt>Pīnyīn</dt> + <dd>{{Pīnyīn}}</dd> + <dt>Deutsch</dt> + <dd>{{Deutsch}}</dd> + {{#Standardaussprache}} + <dt class="t2s-player-heading">汉语</dt> + <dd id="t2s-player-container" class="t2s-player-container"> + <div class="anki-droid-player"> + <tts style="display: none" service="android" voice="zh_CN"> + {{text:Standardaussprache}} + </tts> + </div> + <div class="anki-web-player"> + {{text:Standardaussprache}} + </div> + <div class="anki-builtin-player"> + {{tts zh_CN:Standardaussprache}} + </div> + </dd> + {{/Standardaussprache}} + <dt>Aufnahme</dt> + <dd>{{Audioaufnahme}}</dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen}}</dd> + <dt>Beispiele</dt> + <dd>{{Beispiele}}</dd> + <details class="answer-details"> + <summary> + <span class="answer-details-more">Mehr…</span> + <span class="answer-details-less">Weniger…</span> + </summary> + {{#简体字}} + <dt>简体字</dt> + <dd> + <span class="hanzi-print">{{简体字}}</span> + <div class="strichfolge-animation" no-animate="true"> + {{text:简体字}} + </div> + </dd> + {{/简体字}} + <dt>Radikal (繁體字)</dt> + <dd> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation is-traditional" no-animate="true"> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical"></span> + </div> + </dd> + {{#简体字}} + <dt>Radikal (简体字)</dt> + <dd> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation" no-animate="true"> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical"></span> + </div> + </dd> + {{/简体字}} + </details> + </dl> + + <include src="src/components/notice/notice.html"></include> +</div> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/molaoshi/read_hanzi_traditional/front.html b/src/templates/molaoshi/read_hanzi_traditional/front.html new file mode 100644 index 0000000..99cfaf7 --- /dev/null +++ b/src/templates/molaoshi/read_hanzi_traditional/front.html @@ -0,0 +1,39 @@ +{{#Lesen (繁體字) anlegen}}{{#繁體字}} +<style> + @import url(../../../components/global.css); +</style> + +<div class="exercise front anki-template-hanyu-read-hanzi-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + </header> + + <dl class="prompt translations"> + <dt>繁體字</dt> + <dd> + <span class="hanzi-print">{{繁體字}}</span> + <div class="strichfolge-animation is-traditional" no-animate="true" highlight-radical="answer"> + {{text:繁體字}} + </div> + </dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen (Vorderseite)}}</dd> + </dl> +</div> + +<!-- Suppress speech output on AnkiDroid until card flipped --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> +{{/繁體字}}{{/Lesen (繁體字) anlegen}} \ No newline at end of file diff --git a/src/templates/molaoshi/read_pinyin/back.html b/src/templates/molaoshi/read_pinyin/back.html new file mode 100644 index 0000000..71d7131 --- /dev/null +++ b/src/templates/molaoshi/read_pinyin/back.html @@ -0,0 +1,81 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back anki-template-hanyu-read-pinyin-back"> + <dl class="translations"> + <dt>Deutsch</dt> + <dd>{{Deutsch}}</dd> + <dt>简体字</dt> + <dd> + <span class="hanzi-print">{{简体字}}</span> + <div class="strichfolge-animation" no-animate="true" highlight-radical="true"> + {{text:简体字}} + </div> + </dd> + {{#Standardaussprache}} + <dt class="t2s-player-heading">汉语</dt> + <dd id="t2s-player-container" class="t2s-player-container"> + <div class="anki-droid-player"> + <tts style="display: none" service="android" voice="zh_CN"> + {{text:Standardaussprache}} + </tts> + </div> + <div class="anki-web-player"> + {{text:Standardaussprache}} + </div> + <div class="anki-builtin-player"> + {{tts zh_CN:Standardaussprache}} + </div> + </dd> + {{/Standardaussprache}} + <dt>Aufnahme</dt> + <dd>{{Audioaufnahme}}</dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen}}</dd> + <dt>Beispiele</dt> + <dd>{{Beispiele}}</dd> + <details class="answer-details"> + <summary> + <span class="answer-details-more">Mehr…</span> + <span class="answer-details-less">Weniger…</span> + </summary> + {{#繁體字}} + <dt>繁體字</dt> + <dd> + <span class="hanzi-print">{{繁體字}}</span> + <div class="strichfolge-animation is-traditional" no-animate="true" highlight-radical="true"> + {{text:繁體字}} + </div> + </dd> + {{/繁體字}} + <dt>Radikal (简体字)</dt> + <dd> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation" no-animate="true"> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical"></span> + </div> + </dd> + {{#繁體字}} + <dt>Radikal (繁體字)</dt> + <dd> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation is-traditional" no-animate="true"> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical"></span> + </div> + </dd> + {{/繁體字}} + </details> + </dl> + + <include src="src/components/notice/notice.html"></include> +</div> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/molaoshi/read_pinyin/front.html b/src/templates/molaoshi/read_pinyin/front.html new file mode 100644 index 0000000..7674257 --- /dev/null +++ b/src/templates/molaoshi/read_pinyin/front.html @@ -0,0 +1,34 @@ +{{#Pīnyīn}} +<style> + @import url(../../../components/global.css); +</style> + +<div class="exercise front anki-template-hanyu-read-pinyin-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + </header> + + <dl class="prompt translations"> + <dt>Pīnyīn</dt> + <dd>{{Pīnyīn}}</dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen (Vorderseite)}}</dd> + </dl> +</div> + +<!-- Suppress speech output on AnkiDroid until card flipped --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> +{{/Pīnyīn}} \ No newline at end of file diff --git a/src/templates/molaoshi/speak/back.html b/src/templates/molaoshi/speak/back.html new file mode 100644 index 0000000..b80aea9 --- /dev/null +++ b/src/templates/molaoshi/speak/back.html @@ -0,0 +1,81 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back anki-template-hanyu-speak-back"> + <dl class="translations"> + <dt>Pīnyīn</dt> + <dd>{{Pīnyīn}}</dd> + <dt>简体字</dt> + <dd> + <span class="hanzi-print">{{简体字}}</span> + <div class="strichfolge-animation" no-animate="true" highlight-radical="true"> + {{text:简体字}} + </div> + </dd> + {{#Standardaussprache}} + <dt class="t2s-player-heading">汉语</dt> + <dd id="t2s-player-container" class="t2s-player-container"> + <div class="anki-droid-player"> + <tts style="display: none" service="android" voice="zh_CN"> + {{text:Standardaussprache}} + </tts> + </div> + <div class="anki-web-player"> + {{text:Standardaussprache}} + </div> + <div class="anki-builtin-player"> + {{tts zh_CN:Standardaussprache}} + </div> + </dd> + {{/Standardaussprache}} + <dt>Aufnahme</dt> + <dd>{{Audioaufnahme}}</dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen}}</dd> + <dt>Beispiele</dt> + <dd>{{Beispiele}}</dd> + <details class="answer-details"> + <summary> + <span class="answer-details-more">Mehr…</span> + <span class="answer-details-less">Weniger…</span> + </summary> + {{#繁體字}} + <dt>繁體字</dt> + <dd> + <span class="hanzi-print">{{繁體字}}</span> + <div class="strichfolge-animation is-traditional" no-animate="true" highlight-radical="true"> + {{text:繁體字}} + </div> + </dd> + {{/繁體字}} + <dt>Radikal (简体字)</dt> + <dd> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation" no-animate="true"> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical"></span> + </div> + </dd> + {{#繁體字}} + <dt>Radikal (繁體字)</dt> + <dd> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation is-traditional" no-animate="true"> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical"></span> + </div> + </dd> + {{/繁體字}} + </details> + </dl> + + <include src="src/components/notice/notice.html"></include> +</div> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/molaoshi/speak/front.html b/src/templates/molaoshi/speak/front.html new file mode 100644 index 0000000..a93e52e --- /dev/null +++ b/src/templates/molaoshi/speak/front.html @@ -0,0 +1,34 @@ +{{#Deutsch}} +<style> + @import url(../../../components/global.css); +</style> + +<div class="exercise front anki-template-hanyu-speak-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + </header> + + <dl class="prompt translations"> + <dt>Deutsch</dt> + <dd>{{Deutsch}}</dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen (Vorderseite)}}</dd> + </dl> +</div> + +<!-- Suppress speech output on AnkiDroid until card flipped --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> +{{/Deutsch}} \ No newline at end of file diff --git a/src/templates/molaoshi/write/back.html b/src/templates/molaoshi/write/back.html new file mode 100644 index 0000000..6417876 --- /dev/null +++ b/src/templates/molaoshi/write/back.html @@ -0,0 +1,81 @@ +<div class="front-side-on-back"> + {{FrontSide}} +</div> + +<hr id="answer"> + +<div class="exercise back anki-template-hanyu-write-back"> + <dl class="translations"> + <dt>简体字</dt> + <dd> + <span class="hanzi-print">{{简体字}}</span> + <div class="strichfolge-animation" highlight-radical="true"> + {{text:简体字}} + </div> + </dd> + <dt>Pīnyīn</dt> + <dd>{{Pīnyīn}}</dd> + {{#Standardaussprache}} + <dt class="t2s-player-heading">汉语</dt> + <dd id="t2s-player-container" class="t2s-player-container"> + <div class="anki-droid-player"> + <tts style="display: none" service="android" voice="zh_CN"> + {{text:Standardaussprache}} + </tts> + </div> + <div class="anki-web-player"> + {{text:Standardaussprache}} + </div> + <div class="anki-builtin-player"> + {{tts zh_CN:Standardaussprache}} + </div> + </dd> + {{/Standardaussprache}} + <dt>Aufnahme</dt> + <dd>{{Audioaufnahme}}</dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen}}</dd> + <dt>Beispiele</dt> + <dd>{{Beispiele}}</dd> + <details class="answer-details"> + <summary> + <span class="answer-details-more">Mehr…</span> + <span class="answer-details-less">Weniger…</span> + </summary> + {{#繁體字}} + <dt>繁體字</dt> + <dd> + <span class="hanzi-print">{{繁體字}}</span> + <div class="strichfolge-animation is-traditional" highlight-radical="true"> + {{text:繁體字}} + </div> + </dd> + {{/繁體字}} + <dt>Radikal (简体字)</dt> + <dd> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation" no-animate="true"> + <span hanzi-data="{{text:简体字}}" hanzi-prop="radical"></span> + </div> + </dd> + {{#繁體字}} + <dt>Radikal (繁體字)</dt> + <dd> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical" class="hanzi-print"></span> + <div class="strichfolge-animation is-traditional" no-animate="true"> + <span hanzi-data="{{text:繁體字}}" hanzi-kind="traditional" hanzi-prop="radical"></span> + </div> + </dd> + {{/繁體字}} + </details> + </dl> + + <include src="src/components/notice/notice.html"></include> +</div> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/back' +</script> \ No newline at end of file diff --git a/src/templates/molaoshi/write/front.html b/src/templates/molaoshi/write/front.html new file mode 100644 index 0000000..ed82b42 --- /dev/null +++ b/src/templates/molaoshi/write/front.html @@ -0,0 +1,34 @@ +{{#Deutsch}}{{#Schreiben anlegen}} +<style> + @import url(../../../components/global.css); +</style> + +<div class="exercise front anki-template-hanyu-write-front"> + <header class="card-info"> + <aside class="exercise-category"> + {{Subdeck}} + </aside> + <aside class="exercise-kind"> + {{Card}} + </aside> + </header> + </header> + + <dl class="prompt translations"> + <dt>Deutsch</dt> + <dd>{{Deutsch}}</dd> + <dt>Bemerkungen</dt> + <dd>{{Bemerkungen (Vorderseite)}}</dd> + </dl> +</div> + +<!-- Suppress default speech output and do that from script instead --> +<tts style="display: none" service="android" voice="zh_CN"></tts> + +<script type="module"> + import '../../../components/debug' +</script> +<script type="module"> + import '../../../components/front' +</script> +{{/Schreiben anlegen}}{{/Deutsch}} \ No newline at end of file diff --git a/test/build/fixtures/anki/.apkg-spec.yaml b/test/build/fixtures/anki/.apkg-spec.yaml deleted file mode 100644 index 92ef748..0000000 --- a/test/build/fixtures/anki/.apkg-spec.yaml +++ /dev/null @@ -1,8 +0,0 @@ -content_version: 0.0.1 - -templates: -- q_a - -content: -- import_apkg: - note_type: Q/A Testnotetype \ No newline at end of file diff --git a/test/build/fixtures/anki/Test.apkg b/test/build/fixtures/anki/Test.apkg deleted file mode 100644 index 28a3614f2b228aa8ae1ba806c9914101a758cdcd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 55648 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 diff --git a/test/build/fixtures/csv/.apkg-spec.yaml b/test/build/fixtures/csv/.apkg-spec.yaml deleted file mode 100644 index 274a5ed..0000000 --- a/test/build/fixtures/csv/.apkg-spec.yaml +++ /dev/null @@ -1,18 +0,0 @@ -content_version: 1.0.0 - -templates: -- q_a - -content: -- import_csv: - content_version: 2024-01-19 19:00:00+00:00 - note_type: Q/A Testnotetype - file_patterns: - - '*.csv' - # and to making one deck per card type - deck_name_pattern: '{{card_type}}' - fields_mapping: - - guid - - Question - - Answer - tags: [] \ No newline at end of file diff --git a/test/build/fixtures/csv/content.csv b/test/build/fixtures/csv/content.csv deleted file mode 100644 index 3c98112..0000000 --- a/test/build/fixtures/csv/content.csv +++ /dev/null @@ -1 +0,0 @@ -test-csv-note-1;What is the scientific name of the only tapir living in Asia?;Tapirus indicus \ No newline at end of file diff --git a/test/build/fixtures/csv_updated_content/.apkg-spec.yaml b/test/build/fixtures/csv_updated_content/.apkg-spec.yaml deleted file mode 100644 index c20f61a..0000000 --- a/test/build/fixtures/csv_updated_content/.apkg-spec.yaml +++ /dev/null @@ -1,18 +0,0 @@ -content_version: 1.0.0 - -templates: -- q_a - -content: -- import_csv: - content_version: 2024-01-19 20:00:00+00:00 - note_type: Q/A Testnotetype - file_patterns: - - '*.csv' - # and to making one deck per card type - deck_name_pattern: '{{card_type}}' - fields_mapping: - - guid - - Question - - Answer - tags: [] \ No newline at end of file diff --git a/test/build/fixtures/csv_updated_content/content.csv b/test/build/fixtures/csv_updated_content/content.csv deleted file mode 100644 index d1f9267..0000000 --- a/test/build/fixtures/csv_updated_content/content.csv +++ /dev/null @@ -1 +0,0 @@ -test-csv-note-1;What is the scientific name of the only tapir living in Asia?;Tapirus indicus, Acrocodia indica being an outdated synonym. \ No newline at end of file diff --git a/test/build/fixtures/templates_updated/q_a/.template-spec.yaml b/test/build/fixtures/templates_updated/q_a/.template-spec.yaml deleted file mode 100644 index 02ef56a..0000000 --- a/test/build/fixtures/templates_updated/q_a/.template-spec.yaml +++ /dev/null @@ -1,14 +0,0 @@ -template_version: 2024-01-20 19:00:00+00:00 - -note_type: - id: 2024-01-20 01:00:00+00:00 - name: Q/A Testnotetype - fields: - - Question - - Answer - -card_types: -- name: Q/A Testcardtype - template: q_a - -resource_paths: [] diff --git a/test/build/fixtures/templates_updated/q_a/q_a/back.html b/test/build/fixtures/templates_updated/q_a/q_a/back.html deleted file mode 100644 index 5cc0404..0000000 --- a/test/build/fixtures/templates_updated/q_a/q_a/back.html +++ /dev/null @@ -1 +0,0 @@ -Back: {{Answer}} \ No newline at end of file diff --git a/test/build/fixtures/templates_updated/q_a/q_a/front.html b/test/build/fixtures/templates_updated/q_a/q_a/front.html deleted file mode 100644 index 51c00f1..0000000 --- a/test/build/fixtures/templates_updated/q_a/q_a/front.html +++ /dev/null @@ -1 +0,0 @@ -Front: {{Question}} \ No newline at end of file diff --git a/test/build/test_export_apkgs.py b/test/build/test_export_apkgs.py deleted file mode 100644 index 22b46f4..0000000 --- a/test/build/test_export_apkgs.py +++ /dev/null @@ -1,337 +0,0 @@ -from anki.collection import Collection, ImportAnkiPackageRequest, ImportAnkiPackageOptions -from anki.import_export_pb2 import ImportAnkiPackageUpdateCondition -from build.export_apkgs import export_package_from_spec -from dataclasses import dataclass -from pathlib import Path -from tempfile import TemporaryDirectory -import unittest - -@dataclass -class MockArgs: - content: str - templates_dir: str - output_dir: str - dry_run: bool - -CONTENT_PATH_ANKI = 'test/build/fixtures/anki' -CONTENT_PATH_CSV = 'test/build/fixtures/csv' -CONTENT_PATH_CSV_UPDATED_CONTENT = 'test/build/fixtures/csv_updated_content' -TEMPLATES_PATH = 'test/build/fixtures/templates' -TEMPLATES_PATH_UPDATED = 'test/build/fixtures/templates_updated' - -class TestExportApkgs(unittest.TestCase): - def test_generate_once_and_reimport(self): - """ - Basic sanity check: if the exported package is imported twice, - everything is a duplicate and nothing should change. - """ - with TemporaryDirectory() as temp_collection_dir: - col = Collection(str(Path(temp_collection_dir) / "test.anki2")) - with TemporaryDirectory() as first_export_dir: - args_first = MockArgs( - content=CONTENT_PATH_CSV, - templates_dir=TEMPLATES_PATH, - output_dir=first_export_dir, - dry_run=False) - package = export_package_from_spec( - Path(CONTENT_PATH_CSV) / '.apkg-spec.yaml', - args_first) - - # import the first time, everything is new - result1 = col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - self.assertEqual(len(result1.log.new), 1) - self.assertEqual(len(result1.log.duplicate), 0) - - # now import again, nothing should change - result2 = col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - self.assertEqual(len(result2.log.duplicate) == 1 and len(result2.log.new), 0, - f'Expected the note to be recognized as duplicate.\nLog1:\n{result1.log}\nLog2:\n{result2.log}') - - def test_generate_twice_and_reimport(self): - """ - This checks that if we generate the package twice and import it twice, - then the second import will not change anything because the content is - supposed to be the same. - - If we introduce errors that lead to different note and card IDs being - generated, then this test will fail. - """ - with TemporaryDirectory() as temp_collection_dir: - col = Collection(str(Path(temp_collection_dir) / "test.anki2")) - with TemporaryDirectory() as first_export_dir: - args_first = MockArgs( - content=CONTENT_PATH_CSV, - templates_dir=TEMPLATES_PATH, - output_dir=first_export_dir, - dry_run=False) - with TemporaryDirectory() as second_export_dir: - args_second = MockArgs( - content=CONTENT_PATH_CSV, - templates_dir=TEMPLATES_PATH, - output_dir=second_export_dir, - dry_run=False) - spec_path = Path(CONTENT_PATH_CSV) / '.apkg-spec.yaml' - first_package = export_package_from_spec(spec_path, args_first) - second_package = export_package_from_spec(spec_path, args_second) - - # debug: uncomment to view for testing - # shutil.copy(first_package, './test-export-first.apkg.zip') - # shutil.copy(second_package, './test-export-second.apkg.zip') - - # import the first time, everything is new - result1 = col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(first_package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - self.assertEqual(len(result1.log.new), 1) - self.assertEqual(len(result1.log.duplicate), 0) - - # now import again, nothing should change - result2 = col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(second_package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - self.assertTrue( - len(result2.log.duplicate) == 1 and len(result2.log.new) == 0, - f'Expected second import to be a duplicate, but something else happened\nfirst log: {result1.log}\nsecond log:\n{result2.log}') - - def test_content_update_overwrites_previous_note(self): - """ - Tests that bumping the modification time will update notes from previous versions. - """ - with TemporaryDirectory() as temp_collection_dir: - col = Collection(str(Path(temp_collection_dir) / "test.anki2")) - with TemporaryDirectory() as first_export_dir: - args_first = MockArgs( - content=CONTENT_PATH_CSV, - templates_dir=TEMPLATES_PATH, - output_dir=first_export_dir, - dry_run=False) - with TemporaryDirectory() as second_export_dir: - args_second = MockArgs( - content=CONTENT_PATH_CSV_UPDATED_CONTENT, - templates_dir=TEMPLATES_PATH, - output_dir=second_export_dir, - dry_run=False) - spec_path_old = Path(f'{CONTENT_PATH_CSV}/.apkg-spec.yaml') - spec_path_new = Path(f'{CONTENT_PATH_CSV_UPDATED_CONTENT}/.apkg-spec.yaml') - first_package = export_package_from_spec(spec_path_old, args_first) - second_package = export_package_from_spec(spec_path_new, args_second) - - # import the old version version - result1 = col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(first_package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - self.assertEqual(len(result1.log.updated), 0) - self.assertEqual(len(result1.log.new), 1) - self.assertEqual(len(result1.log.duplicate), 0) - - # now the update - result2 = col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(second_package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - self.assertTrue(len(result2.log.updated) == 1 and len(result2.log.new) == 0 and len(result2.log.duplicate) == 0, - f'Expected the note to be recognized as update.\nLog1:\n{result1.log}\nLog2:\n{result2.log}') - - - def test_template_update_overwrites_previous_template_csv(self): - """ - Tests that bumping the modification time will update notes from previous versions - of CSV content. - """ - with TemporaryDirectory() as temp_collection_dir: - col = Collection(str(Path(temp_collection_dir) / "test.anki2")) - with TemporaryDirectory() as first_export_dir: - args_first = MockArgs( - content=CONTENT_PATH_CSV, - templates_dir=TEMPLATES_PATH, - output_dir=first_export_dir, - dry_run=False) - with TemporaryDirectory() as second_export_dir: - args_second = MockArgs( - content=CONTENT_PATH_CSV, - templates_dir=TEMPLATES_PATH_UPDATED, - output_dir=second_export_dir, - dry_run=False) - spec_path = Path(f'{CONTENT_PATH_CSV}/.apkg-spec.yaml') - first_package = export_package_from_spec(spec_path, args_first) - second_package = export_package_from_spec(spec_path, args_second) - - # debug: uncomment to view for testing - #shutil.copy(first_package, './test-export-first.apkg.zip') - #shutil.copy(second_package, './test-export-second.apkg.zip') - - # import the old version version - col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(first_package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - - template = find_template(col, 'Q/A Testnotetype') - self.assertIsNotNone(template, 'template not found in collection') - self.assertEqual( - template['qfmt'], - '{{Question}}') - self.assertEqual( - template['afmt'], - '{{Answer}}') - - # now the update - result = col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(second_package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - - # for some reason the change is only visible if we reload the collection - col.close() - col = Collection(str(Path(temp_collection_dir) / "test.anki2")) - - template = find_template(col, 'Q/A Testnotetype') - self.assertIsNotNone(template, 'template not found in collection') - self.assertEqual( - template['qfmt'], - 'Front: {{Question}}', - f'Template not updated successfully, log:\n{result.log}') - self.assertEqual( - template['afmt'], - 'Back: {{Answer}}') - - def test_template_update_overwrites_previous_template_anki(self): - """ - Tests that bumping the modification time will update notes from previous versions - of an imported anki package. - """ - with TemporaryDirectory() as temp_collection_dir: - col = Collection(str(Path(temp_collection_dir) / "test.anki2")) - with TemporaryDirectory() as first_export_dir: - args_first = MockArgs( - content=CONTENT_PATH_ANKI, - templates_dir=TEMPLATES_PATH, - output_dir=first_export_dir, - dry_run=False) - with TemporaryDirectory() as second_export_dir: - args_second = MockArgs( - content=CONTENT_PATH_ANKI, - templates_dir=TEMPLATES_PATH_UPDATED, - output_dir=second_export_dir, - dry_run=False) - spec_path = Path(f'{CONTENT_PATH_ANKI}/.apkg-spec.yaml') - first_package = export_package_from_spec(spec_path, args_first) - second_package = export_package_from_spec(spec_path, args_second) - - # debug: uncomment to view for testing - #shutil.copy(first_package, './test-export-first.apkg.zip') - #shutil.copy(second_package, './test-export-second.apkg.zip') - - # import the old version version - col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(first_package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - - template = find_template(col, 'Q/A Testnotetype') - self.assertIsNotNone(template, 'template not found in collection') - self.assertEqual( - template['qfmt'], - '{{Question}}') - self.assertEqual( - template['afmt'], - '{{Answer}}') - - # now the update - result = col.import_anki_package(ImportAnkiPackageRequest( - package_path=str(second_package), - options=ImportAnkiPackageOptions( - merge_notetypes=True, - update_notes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - update_notetypes=ImportAnkiPackageUpdateCondition.IMPORT_ANKI_PACKAGE_UPDATE_CONDITION_IF_NEWER, - with_scheduling=False, - with_deck_configs=False, - ) - )) - - # for some reason the change is only visible if we reload the collection - col.close() - col = Collection(str(Path(temp_collection_dir) / "test.anki2")) - - template = find_template(col, 'Q/A Testnotetype') - self.assertIsNotNone(template, 'template not found in collection') - self.assertEqual( - template['qfmt'], - 'Front: {{Question}}', - f'Template not updated successfully, log:\n{result.log}') - self.assertEqual( - template['afmt'], - 'Back: {{Answer}}') - -def find_template(col: Collection, name: str): - template = None - for name_and_id in col.models.all_names_and_ids(): - if name_and_id.name == name: - if template is None: - template = col.models.get(name_and_id.id)['tmpls'][0] - else: - raise Exception(f'Found more than one template with name {name}') - return template \ No newline at end of file diff --git a/test/templates/hanzi-data.test.ts b/test/templates/hanzi-data.test.ts new file mode 100644 index 0000000..cadfc82 --- /dev/null +++ b/test/templates/hanzi-data.test.ts @@ -0,0 +1,202 @@ +import { StrokeType } from '../../src-common/stroke-encodings' +import { + GetHanziDataKind, + getHanziData +} from '../../src/components/hanzi-data' + +describe('stroke counts', () => { + describe('default kind', () => { + const kind = GetHanziDataKind.DEFAULT + const testCases = [ + { character: '错', expectedCount: '5+8' }, + { character: '你', expectedCount: '2+5' }, + { character: '笔', expectedCount: '6+4' } + ] + for (const testCase of testCases) { + test(`stroke count of ${testCase.character}`, async () => { + const data = await getHanziData({ + char: testCase.character, + kind + }) + const actualCount = data?.count + expect(actualCount).toBe(testCase.expectedCount) + }) + } + }) + describe('traditional kind', () => { + const kind = GetHanziDataKind.TRADITIONAL + const testCases = [ + { character: '紫', expectedCount: '6+6' }, + { character: '幫', expectedCount: '3+14' }, + { character: '處', expectedCount: '6+5' }, + { character: '夏', expectedCount: '3+7' }, + { character: '鄰', expectedCount: '7+12' }, + { character: '圜', expectedCount: '3+13' }, + { character: '璮', expectedCount: '5+13' }, + { character: '刷', expectedCount: '2+6' }, + { character: '戀', expectedCount: '4+19' }, + { character: '矮', expectedCount: '5+8' }, + { character: '驚', expectedCount: '10+13' }, + { character: '雞', expectedCount: '8+10' }, + { character: '顱', expectedCount: '9+16' }, + { character: '襪', expectedCount: '6+15' }, + { character: '勵', expectedCount: '2+15' }, + { character: '藝', expectedCount: '6+15' }, + { character: '歡', expectedCount: '4+18' }, + { character: '戰', expectedCount: '4+12' }, + { character: '翻', expectedCount: '6+12' }, + { character: '敵', expectedCount: '4+11' }, + { character: '彎', expectedCount: '3+19' }, + { character: '籍', expectedCount: '6+14' }, + { character: '餓', expectedCount: '9+7' }, + { character: '隨', expectedCount: '8+13' }, + { character: '翼', expectedCount: '6+11' }, + { character: '響', expectedCount: '9+11' }, + { character: '矊', expectedCount: '5+14' }, + { character: '聲', expectedCount: '6+11' }, + { character: '磬', expectedCount: '5+11' }, + { character: '獸', expectedCount: '4+15' }, + { character: '義', expectedCount: '6+7' }, + { character: '登', expectedCount: '5+7' }, + { character: '灣', expectedCount: '4+22' }, + { character: '驢', expectedCount: '10+16' }, + { character: '壓', expectedCount: '3+14' }, + { character: '避', expectedCount: '7+13' }, + { character: '甩', expectedCount: '5+0' }, + { character: '懈', expectedCount: '4+13' }, + { character: '靈', expectedCount: '8+16' }, + { character: '攤', expectedCount: '4+19' }, + { character: '氧', expectedCount: '4+6' }, + { character: '參', expectedCount: '2+9' }, + { character: '熱', expectedCount: '4+11' }, + { character: '餐', expectedCount: '9+7' }, + { character: '虝', expectedCount: '6+6' }, + { character: '聽', expectedCount: '6+16' } + ] + for (const testCase of testCases) { + test(`stroke count of ${testCase.character}`, async () => { + const data = await getHanziData({ + char: testCase.character, + kind + }) + const actualCount = data?.count + expect(actualCount).toBe(testCase.expectedCount) + }) + } + }) +}) + +describe('stroke types', () => { + const testCases = [ + { + hanzi: '艸', + expected: [ + StrokeType.SHUZHE, + StrokeType.SHU, + StrokeType.PIE, + StrokeType.SHUZHE, + StrokeType.SHU, + StrokeType.SHU + ] + } + ] + for (const { hanzi, expected } of testCases) { + test(hanzi, async () => { + const { strokeTypes } = await getHanziData({ char: hanzi }) + expect(strokeTypes).toEqual(expected) + }) + } +}) + +describe('radicals', () => { + describe('default kind', () => { + const kind = GetHanziDataKind.DEFAULT + const testCases = [ + ['王', '王'], + ['了', '乙'], + ['草', '艹'], + ['笔', '竹'] + ] + for (const [hanzi, expectedRadical] of testCases) { + test(hanzi, async () => { + const data = await getHanziData({ char: hanzi, kind }) + const radical = data?.radical + expect(radical).toBe(expectedRadical) + }) + } + }) + describe('omitted kind', () => { + test('了', async () => { + // no kind also means default + const data = await getHanziData({ char: '了' }) + const radical = data?.radical + expect(radical).toBe('乙') + }) + }) + describe('traditional kind', () => { + const kind = GetHanziDataKind.TRADITIONAL + const testCases = [ + ['王', '玉'], + ['了', '亅'], + ['蘭', '艸'], + ['聽', '耳'], + ['笔', '竹'], + ['齣', '齒'] + ] + for (const [hanzi, expectedRadical] of testCases) { + test(hanzi, async () => { + const data = await getHanziData({ char: hanzi, kind }) + const radical = data?.radical + expect(radical).toBe(expectedRadical) + }) + } + }) +}) + +describe('SVG data', () => { + const mustHave = [ + '凵', + '季', + '木', + '纔', + '裏', + '這', + '阝', + '餵', + '鼕', + '齒' + ] + for (const hanzi of mustHave) { + test(hanzi, async () => { + const data = await getHanziData({ char: hanzi }) + expect(data?.strokes?.length).toBeGreaterThan(0) + }) + } +}) + +describe('SVG data for grass radicals default vs. traditional', () => { + const grassChars = [ + '若', + '草', + '花', + '苦', + '莫', + '苗' + ] + for (const grassChar of grassChars) { + test(grassChar, async () => { + const defaultData = await getHanziData({ char: grassChar }) + const tradData = await getHanziData({ + char: grassChar, + kind: GetHanziDataKind.TRADITIONAL + }) + expect(tradData.strokes.length).toBe(defaultData.strokes.length + 1) + expect(tradData.strokeTypes.slice(0, 4)).toEqual([ + StrokeType.SHU, + StrokeType.HENG, + StrokeType.SHU, + StrokeType.HENG + ]) + }) + } +}) diff --git a/test/templates/is-hanzi.test.ts b/test/templates/is-hanzi.test.ts new file mode 100644 index 0000000..78338ed --- /dev/null +++ b/test/templates/is-hanzi.test.ts @@ -0,0 +1,29 @@ +import { isMaybeHanzi } from '../../src/components/is-hanzi' + +describe('accepts Hanzi', () => { + const samples = [ + '⽱', + '⻊', + '貘', + '貘⻊⽱' + ] + for (const sample of samples) { + test(sample, () => { + expect(isMaybeHanzi(sample)).toBe(true) + }) + } +}) + +describe('rejects Latin characters, umlauts and punctuation', () => { + const samples = [ + '', // empty string is also not hanzi + 'asdfÄÜ?…', + '…', + '-–—' + ] + for (const sample of samples) { + test(sample, () => { + expect(isMaybeHanzi(sample)).toBe(false) + }) + } +}) diff --git a/test/templates/lut.test.ts b/test/templates/lut.test.ts new file mode 100644 index 0000000..894b4ba --- /dev/null +++ b/test/templates/lut.test.ts @@ -0,0 +1,41 @@ +import { getHanziData } from '../../src/components/hanzi-data' +import { lookup } from '../../src/components/hanzi-data/lut' + +describe('table properties', () => { + const testCases = [ + { hanzi: '草', prop: 'radicalMeaningDe', expected: 'Gras' }, + { hanzi: '母', prop: 'radicalMeaningDe', expected: 'Mutter' }, + { + hanzi: '木', + prop: 'strokeTypeNumbers', + expected: ['①', '②', '③', '④'] + }, + { + hanzi: '道', + prop: 'strokeTypeNumbers', + expected: [ + '④', + '③', + '①', + '③', + '②', + '⑤', + '①', + '①', + '①', + '④', + '⑤', + '④' + ] + } + ] + for (const { hanzi, prop, expected } of testCases) { + test(`${prop} of ${hanzi}`, async () => { + const actual = lookup( + await getHanziData({ char: hanzi }), + prop + ) + expect(actual).toEqual(expected) + }) + } +}) -- GitLab