Skip to content

Commit

Permalink
generate deck for front fields
Browse files Browse the repository at this point in the history
  • Loading branch information
krmanik committed Feb 8, 2024
1 parent 8ad1ce8 commit 9a4f3c5
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 75 deletions.
69 changes: 65 additions & 4 deletions src/dict/contants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,61 @@ const FIELDS = {
AUDIO: 'Audio',
};

const DECK_HTML =
`
const DECK_HTML_FRONT =
`
<div id="char_zhuyin">{{Zhuyin}}</div>
<div id="char_pinyin">{{Pinyin}}</div>
<div id="char_sim" class="char-card">{{Simplified}}</div>
<div id="char_trad" class="char-card">{{Traditional}}</div>
<div id="char_meaning" class="meaning-card">{{Definitions}}</div>
<script>
// v1.0.0 - https://github.com/SimonLammer/anki-persistence/blob/eeb2e1a9e37c941dd63e1fe6c2a257f043c40e0d/script.js
if(void 0===window.Persistence){var e="github.com/SimonLammer/anki-persistence/",t="_default";if(window.Persistence_localStorage=function(){var i=!1;try{null!==window.localStorage&&"object"==typeof window.localStorage&&(i=!0,this.clear=function(){for(var t=0;t<localStorage.length;t++){var i=localStorage.key(t);0==i.indexOf(e)&&(localStorage.removeItem(i),t--)}},this.setItem=function(i,n){void 0==n&&(n=i,i=t),localStorage.setItem(e+i,JSON.stringify(n))},this.getItem=function(i){return void 0==i&&(i=t),JSON.parse(localStorage.getItem(e+i))},this.removeItem=function(i){void 0==i&&(i=t),localStorage.removeItem(e+i)})}catch(n){}this.isAvailable=function(){return i}},window.Persistence_sessionStorage=function(){var i=!1;try{"object"==typeof window.sessionStorage&&(i=!0,this.clear=function(){for(var t=0;t<sessionStorage.length;t++){var i=sessionStorage.key(t);0==i.indexOf(e)&&(sessionStorage.removeItem(i),t--)}},this.setItem=function(i,n){void 0==n&&(n=i,i=t),sessionStorage.setItem(e+i,JSON.stringify(n))},this.getItem=function(i){return void 0==i&&(i=t),JSON.parse(sessionStorage.getItem(e+i))},this.removeItem=function(i){void 0==i&&(i=t),sessionStorage.removeItem(e+i)})}catch(n){}this.isAvailable=function(){return i}},window.Persistence_windowKey=function(i){var n=window[i],o=!1;"object"==typeof n&&(o=!0,this.clear=function(){n[e]={}},this.setItem=function(i,o){void 0==o&&(o=i,i=t),n[e][i]=o},this.getItem=function(i){return void 0==i&&(i=t),void 0==n[e][i]?null:n[e][i]},this.removeItem=function(i){void 0==i&&(i=t),delete n[e][i]},void 0==n[e]&&this.clear()),this.isAvailable=function(){return o}},window.Persistence=new Persistence_sessionStorage,navigator.userAgent.indexOf("Mobile")>0&&(window.Persistence=new Persistence_localStorage,Persistence.isAvailable()||(window.Persistence=new Persistence_sessionStorage)),Persistence.isAvailable()||(window.Persistence=new Persistence_windowKey("py")),!Persistence.isAvailable()){var i=window.location.toString().indexOf("title"),n=window.location.toString().indexOf("main",i);i>0&&n>0&&n-i<10&&(window.Persistence=new Persistence_windowKey("qt"))}}
</script>
<script>
var switchIdList = ["text-pinyin", "text-zhuyin", "text-meaning", "text-sim", "text-trad"];
function initSwitchPrefs() {
for (var _id of switchIdList) {
var divId = _id.replace("text-", "char_");
if (Persistence.getItem("back" + _id) == "false") {
document.getElementById(divId).style.display = "none";
}
}
}
if (Persistence.isAvailable()) {
if (window.ankiPlatform == "desktop" || isInWebView()) {
initSwitchPrefs();
} else {
window.addEventListener("load", initSwitchPrefs, false);
}
}
function isInWebView() {
var UA = navigator.userAgent;
if (/iPhone|iPod|iPad/.test(UA)) {
if (/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(UA)) {
return true;
}
}
if (window.location.href.includes("ankiuser.net")) {
return true;
}
return false;
}
</script>
`;

const DECK_HTML_BACK =
`
<div id="char_zhuyin">{{Zhuyin}}</div>
<div id="char_pinyin">{{Pinyin}}</div>
<div id="char_sim" class="char-card">{{Simplified}}</div>
<div id="char_trad" class="char-card">{{Traditional}}</div>
<div id='audio' style='display:none'>{{Audio}}</div>
<div class="modal-footer1">
<a class="btn" id="btnShowMenu" onclick="openSidebar('sidebar')">
<div class="icon">
Expand Down Expand Up @@ -271,7 +324,7 @@ if(void 0===window.Persistence){var e="github.com/SimonLammer/anki-persistence/"
</a>
</div>
<!-----sidebar------>
`
`;

const DECK_CSS =
`
Expand Down Expand Up @@ -995,6 +1048,10 @@ const DECK_HTML_WITH_HANZI_WRITER =
}
</script>
<div id="char_zhuyin">{{Zhuyin}}</div>
<div id="char_pinyin">{{Pinyin}}</div>
<div id="char_sim" class="char-card">{{Simplified}}</div>
<div id="char_trad" class="char-card">{{Traditional}}</div>
<div id="onfinish-character-target-div" class="tappable"></div>
<div id="character-target-div" class="tappable"></div>
<div id="ch_load_status" style="color:#ea2322; margin-top: -36px; display: none;">&#8226;</div>
Expand Down Expand Up @@ -1025,6 +1082,9 @@ const DECK_HTML_WITH_HANZI_WRITER =
<hr>
<div id="char_meaning" class="meaning-card">{{Definitions}}</div>
<!--sidebar-->
<div id="sidebar" class="sidebar">
Expand Down Expand Up @@ -1690,7 +1750,8 @@ const DECK_HTML_WITH_HANZI_WRITER =

export default {
FIELDS,
DECK_HTML,
DECK_HTML_FRONT,
DECK_HTML_BACK,
DECK_HTML_WITH_HANZI_WRITER,
DECK_CSS
};
191 changes: 120 additions & 71 deletions src/pages/create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { Toolbar } from 'primereact/toolbar';
import { Model, Deck, Package } from "genanki-js";

import initSqlJs from "sql.js";
import { Message } from 'primereact/message';

export default function CreateDeck(): JSX.Element {

Expand Down Expand Up @@ -52,7 +53,6 @@ export default function CreateDeck(): JSX.Element {

const prevNextButtonText = [
"",
"Create Deck Fields",
"Create Card Types",
"Input Chinese Characters",
];
Expand Down Expand Up @@ -81,7 +81,7 @@ export default function CreateDeck(): JSX.Element {
];

const additionalComponents = [
{ id: 'coloredHanzi', label: 'Colored Hanzi' },
// { id: 'coloredHanzi', label: 'Colored Hanzi' },
{ id: 'writingComponent', label: 'Writing Component' },
];

Expand Down Expand Up @@ -318,68 +318,100 @@ export default function CreateDeck(): JSX.Element {
let req = [];
let tmpls = [];

fields.forEach(f => {
fields.forEach((f, i) => {
flds.push({ name: f })
req.push([0, "all", [0]]);
req.push([i, "all", [i]]);
});

for (let card in tabContent) {
let frontFields = []
let backFields = []
let hideSimp = true;
let hideTrad = true;
let hidePin = true;
let hideZhu = true;
let hideDef = true;

for (let front of tabContent[card]["front"]) {
let f = `<div id='${front}'>{{${front.split("front")[1]}}}</div>`
let hides = []

for (let front of tabContent[card]["front"]) {
if (front.includes("Simplified")) {
f = `<div id='char_simp'>{{${front.split("front")[1]}}}</div>`
hideSimp = false;
}
if (front.includes("Traditional")) {
f = `<div id='char_trad'>{{${front.split("front")[1]}}}</div>`
hideTrad = false;
}
if (front.includes("Pinyin")) {
f = `<div id='char_pinyin'>{{${front.split("front")[1]}}}</div>`
hidePin = false;
}
if (front.includes("Zhuyin")) {
f = `<div id='char_zhuyin'>{{${front.split("front")[1]}}}</div>`
hideZhu = false;
}
if (front.includes("Definitions")) {
f = `<div id="char_meaning" class="meaning-card">{{${front.split("front")[1]}}}</div>`
}
if (front.includes("Audio")) {
f = `<div id='char_audio'>{{${front.split("front")[1]}}}</div>`
hideDef = false;
}
frontFields.push(f);
}

for (let back of tabContent[card]["back"]) {
let f = `<div id='${back}'>{{${back.split("back")[1]}}}</div>`
// TODO-remove redundant code
if (hideSimp) {
hides.push("char_sim")
}

if (back.includes("Simplified")) {
f = `<div id='char_simp'>{{${back.split("back")[1]}}}</div>`
}
if (back.includes("Traditional")) {
f = `<div id='char_trad'>{{${back.split("back")[1]}}}</div>`
}
if (back.includes("Pinyin")) {
f = `<div id='char_pinyin'>{{${back.split("back")[1]}}}</div>`
}
if (back.includes("Zhuyin")) {
f = `<div id='char_zhuyin'>{{${back.split("back")[1]}}}</div>`
}
if (back.includes("Definitions")) {
f = `<div id="char_meaning" class="meaning-card">{{${back.split("back")[1]}}}</div>`
}
if (back.includes("Audio")) {
f = `<div id='char_audio'>{{${back.split("back")[1]}}}</div>`
}
backFields.push(f);
if (hideTrad) {
hides.push("char_trad")
}

if (hidePin) {
hides.push("char_pinyin")
}

let QFMT = frontFields.join("\n");
let AFMT = backFields.join("\n") + CONSTANTS.DECK_HTML;
if (hideZhu) {
hides.push("char_zhuyin")
}

if (hideDef) {
hides.push("char_meaning")
}

let hideScript = `
<script>
var hideList = ['${hides.join("', '")}'];
function showHide(type, isShow, style = "inline") {
if (isShow) {
document.querySelectorAll(type).forEach(function (val) {
val.style.display = style;
});
} else {
document.querySelectorAll(type).forEach(function (val) {
val.style.display = 'none';
});
}
}
for (var _hide of hideList) {
document.getElementById(_hide).style.display = "none";
var isShowField = document.getElementById(_hide).style.display == "none" ? false : true;
if (_hide == "char_pinyin") {
showHide(".pinyin", isShowField);
}
if (_hide == "char_zhuyin") {
showHide(".zhuyin", isShowField);
}
if (_hide == "char_sim") {
showHide("#char-sim-id", isShowField);
}
if (_hide == "char_trad") {
showHide("#char-trad-id", isShowField);
showHide(".sep", isShowField);
}
}
</script>`;

let QFMT = CONSTANTS.DECK_HTML_FRONT + hideScript;
let AFMT = CONSTANTS.DECK_HTML_BACK;

if (tabContent[card]["additional"].includes("writingComponent")) {
QFMT = frontFields.join("\n") + CONSTANTS.DECK_HTML_WITH_HANZI_WRITER;
QFMT = CONSTANTS.DECK_HTML_WITH_HANZI_WRITER;
AFMT = `<div id="back">{{FrontSide}}</div>`;
}

Expand All @@ -392,14 +424,14 @@ export default function CreateDeck(): JSX.Element {

const m = new Model({
name: "Basic - (Anki-xiehanzi)",
id: "1543634829843",
id: "1372444668843",
flds: flds,
css: CONSTANTS.DECK_CSS,
req: req,
req: [req],
tmpls: tmpls,
});

const d = new Deck(1276438724672, deckName);
const d = new Deck(1372444668672, deckName);

words.forEach(word => {
let Simplified = word.Simplified;
Expand Down Expand Up @@ -447,7 +479,13 @@ export default function CreateDeck(): JSX.Element {
})

let html = `<div class="meaning-container">
<div class="char"><div id="char-sim-id">${simp}</div>${trad}</div>
<div class="char">
<span id="char-sim-id">${simp}</span>
<span class="sep">〔</span>
<span id="char-trad-id">${trad}</span>
<span class="sep">〕</span>
</span>
</div>
<div class="pinyin">${pin[i]}</div>
<div class="zhuyin">${zhu[i]}</div>
<div class="meaning">${def[i]}</div>
Expand All @@ -470,17 +508,37 @@ export default function CreateDeck(): JSX.Element {
p.setSqlJs(db);
p.addDeck(d);

const iconFile = "_MaterialIcons-Regular.woff2";
const blob = await fetch('https://fonts.gstatic.com/s/materialicons/v141/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2')
.then(response => {
if (!response.ok) {
return null;
}
return response.blob();
const mediaFiles = [
"_MaterialIcons-Regular.woff2",
"_characterpop.svg",
"_hanzicraft.png",
"_pleco.png",
"_rtega.png",
"_youdao.png",
"_tatoeba.png"
];

const fetchFile = async (file) => {
const response = await fetch(`./img/${file}`);
if (!response.ok) {
return null;
}
return response.blob();
};

Promise.all(mediaFiles.map(fetchFile))
.then(blobs => {
blobs.forEach((blob, index) => {
if (blob) {
p.addMedia(blob, mediaFiles[index]);
}
});
})
.catch(error => {
console.error("Error fetching or adding media:", error);
}).finally(() => {
p.writeToFile(`${deckName}.apkg`);
});

p.addMedia(blob, iconFile);
p.writeToFile(`${deckName}.apkg`);
}

return (
Expand Down Expand Up @@ -543,20 +601,11 @@ export default function CreateDeck(): JSX.Element {

<h3 className={styles.mt}>Back Side</h3>
<div>
{fieldsArray.map((field, index) => {
if (fields.includes(field.id)) {
let id = `back${field.id}`;
return (
<div key={index}>
<input type="checkbox" id={id}
onChange={() => handleCheckboxChange(id, 'back')}
checked={tabContent[tabs[activeTab]].back.includes(id)}
></input>
<label htmlFor={id}>{field.label}</label>
</div>
);
}
})}
<Message severity="info" text={`
All fields are available in back side, use side bar during deck review
and turn off the fields you don't want to see.
`} />

</div>

<h3 className={styles.mt}>Additional Components</h3>
Expand All @@ -572,7 +621,7 @@ export default function CreateDeck(): JSX.Element {
))}
</div>

<h3 className={styles.mt}>Preview</h3>
{/* <h3 className={styles.mt}>Preview</h3>
<div>
<div className={styles.card_preview}>
<div className={styles.card_preview__front}>
Expand All @@ -590,7 +639,7 @@ export default function CreateDeck(): JSX.Element {
))}
</div>
</div>
</div>
</div> */}

</div>
)}
Expand Down
Binary file added static/img/_MaterialIcons-Regular.woff2
Binary file not shown.
Loading

0 comments on commit 9a4f3c5

Please sign in to comment.