Skip to content

Commit

Permalink
add option to generate deck and download csv
Browse files Browse the repository at this point in the history
  • Loading branch information
krmanik committed Feb 10, 2024
1 parent 9a4f3c5 commit 481fa8b
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 29 deletions.
72 changes: 70 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"@docusaurus/preset-classic": "2.1.0",
"@mdx-js/react": "^1.6.22",
"buffer": "^6.0.3",
"chinese-s2t": "^1.0.0",
"chinese-to-pinyin": "^1.3.1",
"clsx": "^1.2.1",
"crypto-browserify": "^3.12.0",
"css-minimizer-webpack-plugin": "^4.1.0",
Expand All @@ -33,9 +35,11 @@
"react-dom": "^17.0.2",
"react-icons": "^4.4.0",
"react-player": "^2.11.0",
"segmentit": "^2.0.3",
"sql.js": "^1.10.2",
"stream-browserify": "^3.0.0",
"unzipit": "^1.4.3"
"unzipit": "^1.4.3",
"url-loader": "^4.1.1"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.1.0",
Expand Down
7 changes: 5 additions & 2 deletions plugins/custom-docusaurus-plugin/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ module.exports = function (context, options) {
name: 'custom-docusaurus-plugin',
configureWebpack(config, isServer, utils) {
return {
module: {
rules: [],
},
resolve: {
alias: {
path: require.resolve('path-browserify'),
crypto: require.resolve("crypto-browserify"),
buffer: require.resolve("buffer/"),
stream: require.resolve("stream-browserify")
stream: require.resolve("stream-browserify"),
},
fallback: {
fs: false,
Expand All @@ -17,4 +20,4 @@ module.exports = function (context, options) {
};
},
};
};
};
4 changes: 2 additions & 2 deletions src/dict/dict.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { unzip } from 'unzipit';
import pinyinAndZhuyin from './pinyinzhuyin';
import pinzhu from './pinyinzhuyin';

let dict;

Expand Down Expand Up @@ -212,7 +212,7 @@ async function makeHtml(result, showToneColors): Promise<{
// Pinyin

let pinyinClass = 'w-pinyin';
let p = await pinyinAndZhuyin(entry[3], showToneColors, pinyinClass);
let p = await pinzhu.pinyinAndZhuyin(entry[3], showToneColors, pinyinClass);
html[i].pinyin = p[0];
html[i].syllable = entry[3];

Expand Down
11 changes: 5 additions & 6 deletions src/dict/pinyinzhuyin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,6 @@ async function pinyinAndZhuyin(syllables, showToneColors, pinyinClass) {
let zhuyin = '';
let a = syllables.split(/[\s·]+/);

let pinyinzhunyin = {
pinyin: '',
zhuyin: ''
}

for (let i = 0; i < a.length; i++) {
let syllable = a[i];

Expand Down Expand Up @@ -540,4 +535,8 @@ const accentedPinyin2Zhuyin = (syllable) => {
return zhuyinMap[key] + zhuyinTones[tone];
};

export default pinyinAndZhuyin;
export default {
pinyinAndZhuyin,
numericPinyin2Zhuyin,
accentedPinyin2Zhuyin
}
93 changes: 79 additions & 14 deletions src/pages/create.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styles from './index.module.css';

import React, { useEffect, useState } from "react";
import React, { useEffect, useRef, useState } from "react";
import Layout from '@theme/Layout';
import { RiCloseCircleFill } from "react-icons/ri";
import CONSTANTS from '../dict/contants';
Expand All @@ -23,6 +23,11 @@ import { Model, Deck, Package } from "genanki-js";
import initSqlJs from "sql.js";
import { Message } from 'primereact/message';

import Chinese from 'chinese-s2t';
import pinzhu from '../dict/pinyinzhuyin';

import pinyin from "chinese-to-pinyin";

export default function CreateDeck(): JSX.Element {

const [words, setWords] = useState<{
Expand Down Expand Up @@ -50,6 +55,11 @@ export default function CreateDeck(): JSX.Element {
const [selectType, setSelectType] = React.useState({ selectType: 'Word' });
const [texAreaValue, setTexAreaValue] = React.useState<string>('');
const [db, setDb] = useState(null);
const dt = useRef(null);

const exportCSV = (selectionOnly) => {
dt.current.exportCSV({ selectionOnly });
};

const prevNextButtonText = [
"",
Expand Down Expand Up @@ -148,7 +158,36 @@ export default function CreateDeck(): JSX.Element {
});
};

const parser = new DOMParser();
function decodeHtmlEntities(input) {
const htmlEntityRegex = /&#(\d+);|&([^;]+);/g;
const entityMappings = {
772: '̄',
769: '́',
780: '̌',
768: '̀',
nbsp: ' ',
'uuml': 'ü',
};

function replaceEntity(match, decimal, named) {
if (decimal) {
if (entityMappings.hasOwnProperty(decimal)) {
return entityMappings[decimal];
} else {
return match;
}
} else if (named) {
if (entityMappings.hasOwnProperty(named)) {
return entityMappings[named];
} else {
return match;
}
}
}

const decodedText = input.replace(htmlEntityRegex, replaceEntity);
return decodedText;
}

const searchAndAdd = async (word) => {
let res = DICT.search(word);
Expand All @@ -165,9 +204,9 @@ export default function CreateDeck(): JSX.Element {

for (let res of result) {
if (res.simplified == result[0].simplified) {
Pinyin.push(parser.parseFromString(res.pinyin, 'text/html').body.textContent);
Zhuyin.push(parser.parseFromString(res.zhuyin, 'text/html').body.textContent);
Syllable.push(parser.parseFromString(res.syllable, 'text/html').body.textContent);
Pinyin.push(decodeHtmlEntities(res.pinyin));
Zhuyin.push(decodeHtmlEntities(res.zhuyin));
Syllable.push(res.syllable);
Definitions.push(res.definitions)
}
}
Expand Down Expand Up @@ -212,6 +251,7 @@ export default function CreateDeck(): JSX.Element {
const lines = text.split('\n');

let _words = [];
let doNotAdd = [];

for (let line of lines) {
let res = DICT.search(line);
Expand All @@ -223,17 +263,38 @@ export default function CreateDeck(): JSX.Element {

for (let res of result) {
if (res.simplified == result[0].simplified) {
Pinyin.push(parser.parseFromString(res.pinyin, 'text/html').body.textContent);
Zhuyin.push(parser.parseFromString(res.zhuyin, 'text/html').body.textContent);
Syllable.push(parser.parseFromString(res.syllable, 'text/html').body.textContent);
Definitions.push(res.definitions)
if (line.trim() !== result[0].simplified) {
doNotAdd.push(line.trim());
} else {
Pinyin.push(decodeHtmlEntities(res.pinyin));
Zhuyin.push(decodeHtmlEntities(res.zhuyin));
Syllable.push(res.syllable);
Definitions.push(res.definitions)
}
}
}

if (words.some(w => w.Simplified === result[0].simplified)) {
continue;
}

if (doNotAdd.includes(line.trim())) {
const url = `https://translate.googleapis.com/translate_a/single?client=gtx&sl=zh-CN&tl=en-US&dt=t&q=${line.trim()}`;
const response = await fetch(url);
const data = await response.json();

result[0].simplified = line.trim();
result[0].traditional = Chinese.s2t(line.trim());

let pin = pinyin(line.trim(), {toneToNumber: true});
let pizh = await pinzhu.pinyinAndZhuyin(pin, "", "");

Pinyin = [decodeHtmlEntities(pizh[1])];
Zhuyin = [decodeHtmlEntities(pizh[2])];
Syllable = Pinyin;
Definitions.push(data[0][0][0]);
}

_words.push({
Simplified: result[0].simplified,
Traditional: result[0].traditional,
Expand All @@ -247,6 +308,7 @@ export default function CreateDeck(): JSX.Element {
setWords([...words, ..._words]);

console.log(_words);
console.log(doNotAdd);

// not react way but for now use this
document.querySelector(".p-fileupload-file-badge").classList.remove("p-badge-warning");
Expand Down Expand Up @@ -288,9 +350,9 @@ export default function CreateDeck(): JSX.Element {

for (let res of result) {
if (res.simplified == result[0].simplified) {
Pinyin.push(parser.parseFromString(res.pinyin, 'text/html').body.textContent);
Zhuyin.push(parser.parseFromString(res.zhuyin, 'text/html').body.textContent);
Syllable.push(parser.parseFromString(res.syllable, 'text/html').body.textContent);
Pinyin.push(decodeHtmlEntities(res.pinyin));
Zhuyin.push(decodeHtmlEntities(res.zhuyin));
Syllable.push(res.syllable);
Definitions.push(res.definitions)
}
}
Expand Down Expand Up @@ -696,12 +758,15 @@ for (var _hide of hideList) {
</React.Fragment>
)}
end={(
<Button className={`${styles.mr_2} mr-2`} label="Generate Deck" onClick={generateDeck} />
<React.Fragment>
<Button className={`${styles.mr_2} mr-2`} label="Export CSV" onClick={exportCSV} />
<Button className={`${styles.mr_2} mr-2`} label="Generate Deck" onClick={generateDeck} />
</React.Fragment>
)} />
</div>

<DataTable
paginator rows={10}
ref={dt} paginator rows={10} rowsPerPageOptions={[5, 10, 25, 50, 100, 500]}
selectionMode={rowClick ? null : 'radiobutton'}
selection={selectWord} onSelectionChange={(e) => setSelectWord(e.value)}
value={words} tableStyle={{ minWidth: '60rem' }}
Expand Down
Loading

0 comments on commit 481fa8b

Please sign in to comment.