aboutsummaryrefslogtreecommitdiff
path: root/anki-card-temlate
diff options
context:
space:
mode:
Diffstat (limited to 'anki-card-temlate')
-rw-r--r--anki-card-temlate/.gitignore2
-rw-r--r--anki-card-temlate/back-template.m411
-rw-r--r--anki-card-temlate/card.css33
-rw-r--r--anki-card-temlate/card.html22
-rw-r--r--anki-card-temlate/card.js70
-rw-r--r--anki-card-temlate/front-template.m47
-rw-r--r--anki-card-temlate/makefile18
-rw-r--r--anki-card-temlate/readme.md70
8 files changed, 233 insertions, 0 deletions
diff --git a/anki-card-temlate/.gitignore b/anki-card-temlate/.gitignore
new file mode 100644
index 0000000..7bfb9f9
--- /dev/null
+++ b/anki-card-temlate/.gitignore
@@ -0,0 +1,2 @@
+*-template.html
+*.min.*
diff --git a/anki-card-temlate/back-template.m4 b/anki-card-temlate/back-template.m4
new file mode 100644
index 0000000..1a0607d
--- /dev/null
+++ b/anki-card-temlate/back-template.m4
@@ -0,0 +1,11 @@
+<div class="card back">
+<span id="sentence" class="parse foreign">{{Complete sentence}}</span>
+<hr class="split">
+<span id="target-word-reading" class="foreign">{{Target word reading}}</span>
+<span id="target-word-translation" class="native">{{Target word translation}}</span>
+<span id="sentence-translation" class="native spoiler hidden">{{Complete sentence translation}}</span>
+</div>
+
+<style>undivert(`card.min.css')</style>
+<script defer>undivert(`card.min.js')</script>
+
diff --git a/anki-card-temlate/card.css b/anki-card-temlate/card.css
new file mode 100644
index 0000000..8c2b0d0
--- /dev/null
+++ b/anki-card-temlate/card.css
@@ -0,0 +1,33 @@
+.mobile .card .foreign { font-size: 1.75rem; }
+.mobile .card .native { font-size: 1.25rem; }
+
+.card .foreign { font-size: 1.5rem; }
+.card .native { font-size: 1.0rem; }
+
+.card { text-align: center; }
+.card span { display: block; }
+
+hr {
+ height: 10px;
+ border: none;
+ opacity: 20%;
+}
+hr { background-color: black; }
+.nightMode hr { background-color: white; }
+
+.card.front #target-word-reading,
+.card.front #target-word-translation,
+.card.front #sentence-translation,
+.card.front hr,
+.card.front ruby rt.hidden {
+ display: none;
+}
+
+#sentence-translation { margin-top: 1em; }
+
+.spoiler {
+ transition: filter 300ms;
+ cursor: pointer;
+}
+.spoiler.hidden { filter: blur(0.3rem); }
+.spoiler.visible { filter: blur(0rem); }
diff --git a/anki-card-temlate/card.html b/anki-card-temlate/card.html
new file mode 100644
index 0000000..71ca300
--- /dev/null
+++ b/anki-card-temlate/card.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset='utf-8'>
+ <title>card template test</title>
+ <link rel='stylesheet' type='text/css' media='screen' href='./card.css'>
+ <script defer src='./card.js'></script>
+</head>
+<body>
+
+<div class="card back">
+<span id="sentence" class="parse foreign">[俺](おれ)の[目](め)の[前](まえ)に{全}(ぜん)[裸](はだか)のアリスが*[立](た)っていた*。\n\*escape\* (<i>test</i>)</span>
+<hr class="split">
+<span id="target-word-reading" class="foreign">立つ【た・つ】</span>
+<span id="target-word-translation" class="native">To stand</span>
+<span id="sentence-translation" class="native spoiler hidden">Before my eyes stood Alice, butt-naked.</span>
+</div>
+
+<button onclick="document.getElementsByClassName('card')[0].classList.toggle('back'); document.getElementsByClassName('card')[0].classList.toggle('front')">toggle view</button>
+
+</span>
+</html>
diff --git a/anki-card-temlate/card.js b/anki-card-temlate/card.js
new file mode 100644
index 0000000..0509c3e
--- /dev/null
+++ b/anki-card-temlate/card.js
@@ -0,0 +1,70 @@
+function parseSentence(input) {
+ var bold = false; // currently bold
+ var mode = "normal"; // normal, kanji, reading
+ var out = ""; // output html
+
+ var alwaysvisisble = false; // if furigana is always visible (on front of card)
+ var kanji = ""; // current kanji
+ var reading = ""; // current kanji reading
+
+ for (var i = 0; i < input.length; i++) {
+ // escape characters preceded by \
+ if (input[i] == "\\") {
+ var escaped = input[i+1];
+ if (escaped == "n") escaped = "<br>"; // newline
+ out += escaped; i++; continue;
+ }
+ // parse *test* into <b>test</b>
+ if (input[i] == "*") { bold = !bold; out += `<${bold ? "" : "/"}b>`; continue; }
+
+ // parse [kanji](reading) into ruby text
+ // [kanji](reading) is only visible on card back
+ // {kanji}(reading) is always visible
+ if (mode == "normal" && input[i] == "[") // hidden reading kanji open
+ { kanji = ""; mode = "kanji"; alwaysvisisble = false; continue; }
+ if (mode == "normal" && input[i] == "{") // always visible reading kanji open
+ { kanji = ""; mode = "kanji"; alwaysvisisble = true; continue; }
+ if (mode == "kanji" && input[i] == "]") continue; // hidden reading kanji close
+ if (mode == "kanji" && input[i] == "}") continue; // always visible reading kanji close
+ if (mode == "kanji" && kanji.length > 0 && input[i] == "(") // reading open
+ { reading = ""; mode = "reading"; continue; }
+ if (mode == "reading" && input[i] == ")") { // reading close
+ mode = "normal";
+ out += `<ruby>${kanji}<rt class="${alwaysvisisble ? 'visible' : 'hidden'}">${reading}</rt></ruby>`;
+ continue;
+ }
+
+ // add current character to selected mode buffer
+ if (mode == "normal") out += input[i];
+ if (mode == "kanji") kanji += input[i];
+ if (mode == "reading") reading += input[i];
+ }
+
+ return out;
+}
+
+function run() {
+ // parse all elements with class parse
+ for (var el of document.getElementsByClassName("parse")) {
+ if (el.classList.contains("parsed")) continue; // ignore already parsed elements
+ el.innerHTML = parseSentence(el.innerHTML); // parse
+ el.classList.remove("parse"); // mark as parsed
+ el.classList.add("parsed");
+ }
+
+ // toggle spoiler by clicking
+ for (var el of document.getElementsByClassName("spoiler")) {
+ el.onclick = function () {
+ this.classList.toggle("hidden");
+ this.classList.toggle("visible");
+ };
+ }
+
+ // remove spoiler from sentence translation if word reading field is empty
+ if(document.getElementById("target-word-reading").innerText.length == 0) {
+ document.getElementById("sentence-translation").classList.remove("hidden");
+ }
+}
+
+run();
+window.onload = () => run();
diff --git a/anki-card-temlate/front-template.m4 b/anki-card-temlate/front-template.m4
new file mode 100644
index 0000000..bb1fdb9
--- /dev/null
+++ b/anki-card-temlate/front-template.m4
@@ -0,0 +1,7 @@
+<div class="card front">
+<span id="sentence" class="parse foreign">{{Complete sentence}}</span>
+</div>
+
+<style>undivert(`card.min.css')</style>
+<script defer>undivert(`card.min.js')</script>
+
diff --git a/anki-card-temlate/makefile b/anki-card-temlate/makefile
new file mode 100644
index 0000000..8b715d3
--- /dev/null
+++ b/anki-card-temlate/makefile
@@ -0,0 +1,18 @@
+all: back-template.html front-template.html
+
+.PRECIOUS: card.min.js
+
+card.min.js: card.js
+ sed 's/\/\/.*$$//g' $< | tr '\n' ' ' | sed 's/\t//g' | sed 's/ */ /g' > $@
+
+card.min.css: card.css
+ cat $< | tr '\n' ' ' | sed 's/\t//g' | sed 's/ */ /g' > $@
+
+%.html: %.m4
+ m4 $< > $@
+
+back-template.html: card.min.js card.min.css
+front-template.html: card.min.js card.min.css
+
+clean:
+ $(RM) back-template.html front-template.html card.min.js
diff --git a/anki-card-temlate/readme.md b/anki-card-temlate/readme.md
new file mode 100644
index 0000000..9de275d
--- /dev/null
+++ b/anki-card-temlate/readme.md
@@ -0,0 +1,70 @@
+# anki sentence mining template
+
+work in progress
+
+this is an anki card template for sentence mining. it has fields for a foreign
+sentence, foreign word, translated word and an optional translated sentence. it
+supports a markdown-like [syntax](#syntax) for adding furigana that is visible
+on either both sides or only on the back side.
+
+## example
+
+### input
+
+|Field|Value|
+|-|-|
+|Complete sentence|`[家](うち)の{主}(あるじ)を*なめるなよ*…`|
+|Target word reading|`舐める【なめる】`|
+|Target word translation|`To underestimate`|
+|Complete sentence translation|`Don't underestimate the master of the house...`|
+
+### front
+
+<div class="card front" align="center" style="border: solid 2px gray; padding: 10px;">
+<span class="sentence parsed">家の<ruby>主<rt class="visible">あるじ</rt></ruby>を<b>なめるなよ</b>…</span>
+</div>
+
+### back
+
+<div class="card back" align="center" style="border: solid 2px gray; padding: 10px;">
+<span class="sentence parsed"><ruby>家<rt class="hidden">うち</rt></ruby>の<ruby>主<rt class="visible">あるじ</rt></ruby>を<b>なめるなよ</b>…</span>
+<hr class="split">
+<span class="target-word-reading">舐める【なめる】</span><br>
+<span class="target-word-translation">To underestimate</span><br>
+<span class="sentence-translation">Don't underestimate the master of the house...</span>
+</div>
+
+## syntax
+
+html is passed through, so inline styling (should) still work.
+
+|input|html output|example|
+|-|-|-|
+|`[kanji](furigana)`|`<ruby>kanji<rt>furigana</rt></ruby>`<br>(furigana visible on back side only)|<ruby>kanji<rt>furigana</rt></ruby>|
+|`{kanji}(furigana)`|`<ruby>kanji<rt>furigana</rt></ruby>`<br>(furigana visible on both sides)|<ruby>kanji<rt>furigana</rt></ruby>|
+|`*text*`|`<b>text</b>` (bold)|<b>text</b>|
+|`a\nb`|`a<br>b` (line break)|a<br>b|
+|`\\`|`\` (backslash)|\\|
+|`\[escaped](this)`|`[escaped](this)` (escaped furigana)|\[escaped](this)|
+
+## set-up
+
+i don't know how to create a teplate deck (if that's even a thing), so these
+are instructions to apply to an empty deck.
+
+1. run `make` to generate files
+2. Under Tools > Manage note types > (note type here) > Fields, make sure the
+ following fields exist (might be case-sensitive):
+ | |name|description|
+ |-|----|-----------|
+ |1|Complete sentence|Complete sentence with furigana and target word in bold|
+ |2|Target word reading|Dictionary reading of word (with word type)|
+ |3|Target word translation|(In context) translation of target word|
+ |4|Complete sentence translation|Complete sentence translation|
+3. In the 'Browse' view, click on Cards... (you might need to create a
+ temporary card in a deck) and paste the contents of front-template.html and
+ back-template.html in the front template and back template of the card type.
+ Make sure the Styling tab doesn't contain any code as this will override the
+ built-in styles.
+4. Profit
+