aboutsummaryrefslogtreecommitdiff
path: root/ext/bg/js/dictionary.js
diff options
context:
space:
mode:
Diffstat (limited to 'ext/bg/js/dictionary.js')
-rw-r--r--ext/bg/js/dictionary.js216
1 files changed, 176 insertions, 40 deletions
diff --git a/ext/bg/js/dictionary.js b/ext/bg/js/dictionary.js
index a6438523..4562c821 100644
--- a/ext/bg/js/dictionary.js
+++ b/ext/bg/js/dictionary.js
@@ -19,63 +19,199 @@
class Dictionary {
constructor() {
- this.termDicts = {};
- this.kanjiDicts = {};
+ this.db = null;
+ this.dbVer = 1;
+ this.entities = null;
}
- addTermDict(name, dict) {
- this.termDicts[name] = dict;
- }
+ initDb() {
+ if (this.db !== null) {
+ return Promise.reject('database already initialized');
+ }
- addKanjiDict(name, dict) {
- this.kanjiDicts[name] = dict;
+ this.db = new Dexie('dict');
+ this.db.version(1).stores({
+ terms: '++id,expression,reading',
+ entities: '++,name',
+ kanji: '++,character',
+ meta: 'name,value',
+ });
}
- findTerm(term) {
- let results = [];
+ prepareDb() {
+ this.initDb();
- for (let name in this.termDicts) {
- const dict = this.termDicts[name];
- if (!(term in dict.i)) {
- continue;
+ return this.db.meta.get('version').then(row => {
+ return row ? row.value : 0;
+ }).catch(() => {
+ return 0;
+ }).then(version => {
+ if (this.dbVer === version) {
+ return true;
}
- const indices = dict.i[term].split(' ').map(Number);
- results = results.concat(
- indices.map(index => {
- const [e, r, t, ...g] = dict.d[index];
- return {
- expression: e,
- reading: r,
- tags: t.split(' '),
- glossary: g,
- entities: dict.e,
- id: index
- };
- })
- );
+ const db = this.db;
+ this.db.close();
+ this.db = null;
+
+ return db.delete().then(() => {
+ this.initDb();
+ return false;
+ });
+ });
+ }
+
+ sealDb() {
+ if (this.db === null) {
+ return Promise.reject('database not initialized');
}
- return results;
+ return this.db.meta.put({name: 'version', value: this.dbVer});
+ }
+
+ findTerm(term) {
+ if (this.db === null) {
+ return Promise.reject('database not initialized');
+ }
+
+ const results = [];
+ return this.db.terms.where('expression').equals(term).or('reading').equals(term).each(row => {
+ results.push({
+ expression: row.expression,
+ reading: row.reading,
+ tags: row.tags.split(' '),
+ glossary: row.glossary,
+ id: row.id
+ });
+ }).then(() => {
+ return this.getEntities();
+ }).then(entities => {
+ for (const result of results) {
+ result.entities = entities;
+ }
+
+ return results;
+ });
}
findKanji(kanji) {
+ if (this.db === null) {
+ return Promise.reject('database not initialized');
+ }
+
const results = [];
+ return this.db.kanji.where('character').equals(kanji).each(row => {
+ results.push({
+ character: row.character,
+ onyomi: row.onyomi.split(' '),
+ kunyomi: row.kunyomi.split(' '),
+ tags: row.tags.split(' '),
+ glossary: row.meanings
+ });
+ }).then(() => results);
+ }
- for (let name in this.kanjiDicts) {
- const def = this.kanjiDicts[name].c[kanji];
- if (def) {
- const [k, o, t, ...g] = def;
- results.push({
- character: kanji,
- kunyomi: k.split(' '),
- onyomi: o.split(' '),
- tags: t.split(' '),
- glossary: g
- });
+ getEntities(tags) {
+ if (this.db === null) {
+ return Promise.reject('database not initialized');
+ }
+
+ if (this.entities !== null) {
+ return Promise.resolve(this.entities);
+ }
+
+ return this.db.entities.toArray(rows => {
+ this.entities = {};
+ for (const row of rows) {
+ this.entities[row.name] = row.value;
+ }
+
+ return this.entities;
+ });
+ }
+
+ importTermDict(indexUrl, callback) {
+ if (this.db === null) {
+ return Promise.reject('database not initialized');
+ }
+
+ const indexDir = indexUrl.slice(0, indexUrl.lastIndexOf('/'));
+ return loadJson(indexUrl).then(index => {
+ const entities = [];
+ for (const [name, value] of index.ents) {
+ entities.push({name, value});
}
+
+ return this.db.entities.bulkAdd(entities).then(() => {
+ if (this.entities === null) {
+ this.entities = {};
+ }
+
+ for (const entity of entities) {
+ this.entities[entity.name] = entity.value;
+ }
+ }).then(() => {
+ const loaders = [];
+ for (let i = 1; i <= index.banks; ++i) {
+ const bankUrl = `${indexDir}/bank_${i}.json`;
+ loaders.push(() => {
+ return loadJson(bankUrl).then(definitions => {
+ const rows = [];
+ for (const [expression, reading, tags, ...glossary] of definitions) {
+ rows.push({expression, reading, tags, glossary});
+ }
+
+ return this.db.terms.bulkAdd(rows).then(() => {
+ if (callback) {
+ callback(i, index.banks, indexUrl);
+ }
+ });
+ });
+ });
+ }
+
+ let chain = Promise.resolve();
+ for (const loader of loaders) {
+ chain = chain.then(loader);
+ }
+
+ return chain;
+ });
+ });
+ }
+
+ importKanjiDict(indexUrl, callback) {
+ if (this.db === null) {
+ return Promise.reject('database not initialized');
}
- return results;
+ const indexDir = indexUrl.slice(0, indexUrl.lastIndexOf('/'));
+ return loadJson(indexUrl).then(index => {
+ const loaders = [];
+ for (let i = 1; i <= index.banks; ++i) {
+ const bankUrl = `${indexDir}/bank_${i}.json`;
+ loaders.push(() => {
+ return loadJson(bankUrl).then(definitions => {
+ const rows = [];
+ for (const [character, onyomi, kunyomi, tags, ...meanings] of definitions) {
+ rows.push({character, onyomi, kunyomi, tags, meanings});
+ }
+
+ return this.db.kanji.bulkAdd(rows).then(() => {
+ if (callback) {
+ callback(i, index.banks, indexUrl);
+ }
+ });
+ });
+ });
+ }
+
+ let chain = Promise.resolve();
+ for (const loader of loaders) {
+ chain = chain.then(loader);
+ }
+
+ return chain;
+ });
}
}