Merge branch 'master' into firefox-amo
This commit is contained in:
commit
00c20aed42
18
README.md
18
README.md
@ -55,13 +55,15 @@ primary language is not English, you may consider also importing the English ver
|
|||||||
* [jmdict_swedish.zip](https://foosoft.net/projects/yomichan/dl/dict/jmdict_swedish.zip)
|
* [jmdict_swedish.zip](https://foosoft.net/projects/yomichan/dl/dict/jmdict_swedish.zip)
|
||||||
* **[JMnedict](http://www.edrdg.org/enamdict/enamdict_doc.html)** (Japanese names)
|
* **[JMnedict](http://www.edrdg.org/enamdict/enamdict_doc.html)** (Japanese names)
|
||||||
* [jmnedict.zip](https://foosoft.net/projects/yomichan/dl/dict/jmnedict.zip)
|
* [jmnedict.zip](https://foosoft.net/projects/yomichan/dl/dict/jmnedict.zip)
|
||||||
* **[KANJIDIC](http://nihongo.monash.edu/kanjidic2/index.html)** (Japanese Kanji)
|
|
||||||
* [kanjidic_english.zip](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_english.zip)
|
|
||||||
* [kanjidic_french.zip](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_french.zip)
|
|
||||||
* [kanjidic_portuguese.zip](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_portuguese.zip)
|
|
||||||
* [kanjidic_spanish.zip](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_spanish.zip)
|
|
||||||
* **[KireiCake](https://kireicake.com/rikaicakes/)** (Japanese slang)
|
* **[KireiCake](https://kireicake.com/rikaicakes/)** (Japanese slang)
|
||||||
* [kireicake.zip](https://foosoft.net/projects/yomichan/dl/dict/kireicake.zip)
|
* [kireicake.zip](https://foosoft.net/projects/yomichan/dl/dict/kireicake.zip)
|
||||||
|
* **[KANJIDIC](http://nihongo.monash.edu/kanjidic2/index.html)** (Japanese Kanji)
|
||||||
|
* [kanjidic_english.zip](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_english.zip) ([ver. 1.3.5 and older](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_english_old.zip))
|
||||||
|
* [kanjidic_french.zip](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_french.zip) ([ver. 1.3.5 and older](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_french_old.zip))
|
||||||
|
* [kanjidic_portuguese.zip](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_portuguese.zip) ([ver. 1.3.5 and older](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_portuguese_old.zip))
|
||||||
|
* [kanjidic_spanish.zip](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_spanish.zip) ([ver. 1.3.5 and older](https://foosoft.net/projects/yomichan/dl/dict/kanjidic_spanish_old.zip))
|
||||||
|
* **[Innocent Corpus](https://forum.koohii.com/post-168613.html#pid168613)** (Frequency list of terms and Kanji in 5000+ novels)
|
||||||
|
* [innocent_corpus.zip](https://foosoft.net/projects/yomichan/dl/dict/innocent_corpus.zip)
|
||||||
|
|
||||||
## Basic Usage ##
|
## Basic Usage ##
|
||||||
|
|
||||||
@ -240,6 +242,12 @@ exact versions used for distribution.
|
|||||||
|
|
||||||
## Frequently Asked Questions ##
|
## Frequently Asked Questions ##
|
||||||
|
|
||||||
|
* **Why does the Kanji results page display "No data found" for several fields?**
|
||||||
|
|
||||||
|
You are using data from the KANJIDIC dictionary that was exported for an earlier version of Yomichan. It does not
|
||||||
|
contain the additional information which newer versions of Yomichan expect. Please purge your database and install
|
||||||
|
the latest version of the KANJIDIC to see additional information about characters.
|
||||||
|
|
||||||
* **Can I still create cards without HTML formatting? The option for it is gone!**
|
* **Can I still create cards without HTML formatting? The option for it is gone!**
|
||||||
|
|
||||||
Developing Yomichan is a constant balance between including useful features and keeping complexity at a minimum.
|
Developing Yomichan is a constant balance between including useful features and keeping complexity at a minimum.
|
||||||
|
@ -62,7 +62,7 @@ class AnkiConnect {
|
|||||||
if (this.remoteVersion < this.localVersion) {
|
if (this.remoteVersion < this.localVersion) {
|
||||||
this.remoteVersion = await this.ankiInvoke('version');
|
this.remoteVersion = await this.ankiInvoke('version');
|
||||||
if (this.remoteVersion < this.localVersion) {
|
if (this.remoteVersion < this.localVersion) {
|
||||||
throw 'extension and plugin versions incompatible';
|
throw 'Extension and plugin versions incompatible';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ async function apiTermsFind(text) {
|
|||||||
|
|
||||||
const searcher = options.general.groupResults ?
|
const searcher = options.general.groupResults ?
|
||||||
translator.findTermsGrouped.bind(translator) :
|
translator.findTermsGrouped.bind(translator) :
|
||||||
translator.findTerms.bind(translator);
|
translator.findTermsSplit.bind(translator);
|
||||||
|
|
||||||
const {definitions, length} = await searcher(
|
const {definitions, length} = await searcher(
|
||||||
text,
|
text,
|
||||||
|
@ -57,7 +57,7 @@ async function audioBuildUrl(definition, mode, cache={}) {
|
|||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post');
|
xhr.open('POST', 'https://www.japanesepod101.com/learningcenter/reference/dictionary_post');
|
||||||
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||||
xhr.addEventListener('error', () => reject('failed to scrape audio data'));
|
xhr.addEventListener('error', () => reject('Failed to scrape audio data'));
|
||||||
xhr.addEventListener('load', () => {
|
xhr.addEventListener('load', () => {
|
||||||
cache[definition.expression] = xhr.responseText;
|
cache[definition.expression] = xhr.responseText;
|
||||||
resolve(xhr.responseText);
|
resolve(xhr.responseText);
|
||||||
@ -87,7 +87,7 @@ async function audioBuildUrl(definition, mode, cache={}) {
|
|||||||
} else {
|
} else {
|
||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', `http://jisho.org/search/${definition.expression}`);
|
xhr.open('GET', `http://jisho.org/search/${definition.expression}`);
|
||||||
xhr.addEventListener('error', () => reject('failed to scrape audio data'));
|
xhr.addEventListener('error', () => reject('Failed to scrape audio data'));
|
||||||
xhr.addEventListener('load', () => {
|
xhr.addEventListener('load', () => {
|
||||||
cache[definition.expression] = xhr.responseText;
|
cache[definition.expression] = xhr.responseText;
|
||||||
resolve(xhr.responseText);
|
resolve(xhr.responseText);
|
||||||
|
@ -71,7 +71,7 @@ class Backend {
|
|||||||
return promise.then(result => {
|
return promise.then(result => {
|
||||||
callback({result});
|
callback({result});
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
callback({error});
|
callback({error: error.toString ? error.toString() : error});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,44 +20,33 @@
|
|||||||
class Database {
|
class Database {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.db = null;
|
this.db = null;
|
||||||
this.version = 2;
|
|
||||||
this.tagCache = {};
|
this.tagCache = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
async sanitize() {
|
|
||||||
try {
|
|
||||||
const db = new Dexie('dict');
|
|
||||||
await db.open();
|
|
||||||
db.close();
|
|
||||||
if (db.verno !== this.version) {
|
|
||||||
await db.delete();
|
|
||||||
}
|
|
||||||
} catch(e) {
|
|
||||||
// NOP
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
if (this.db) {
|
if (this.db) {
|
||||||
throw 'database already initialized';
|
throw 'Database already initialized';
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.sanitize();
|
|
||||||
|
|
||||||
this.db = new Dexie('dict');
|
this.db = new Dexie('dict');
|
||||||
this.db.version(this.version).stores({
|
this.db.version(2).stores({
|
||||||
terms: '++id,dictionary,expression,reading',
|
terms: '++id,dictionary,expression,reading',
|
||||||
kanji: '++,dictionary,character',
|
kanji: '++,dictionary,character',
|
||||||
tagMeta: '++,dictionary',
|
tagMeta: '++,dictionary',
|
||||||
dictionaries: '++,title,version'
|
dictionaries: '++,title,version'
|
||||||
});
|
});
|
||||||
|
this.db.version(3).stores({
|
||||||
|
termMeta: '++,dictionary,expression',
|
||||||
|
kanjiMeta: '++,dictionary,character',
|
||||||
|
tagMeta: '++,dictionary,name'
|
||||||
|
});
|
||||||
|
|
||||||
await this.db.open();
|
await this.db.open();
|
||||||
}
|
}
|
||||||
|
|
||||||
async purge() {
|
async purge() {
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
throw 'database not initialized';
|
throw 'Database not initialized';
|
||||||
}
|
}
|
||||||
|
|
||||||
this.db.close();
|
this.db.close();
|
||||||
@ -70,7 +59,7 @@ class Database {
|
|||||||
|
|
||||||
async findTerms(term, titles) {
|
async findTerms(term, titles) {
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
throw 'database not initialized';
|
throw 'Database not initialized';
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = [];
|
const results = [];
|
||||||
@ -89,17 +78,31 @@ class Database {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.cacheTagMeta(titles);
|
return results;
|
||||||
for (const result of results) {
|
}
|
||||||
result.tagMeta = this.tagCache[result.dictionary] || {};
|
|
||||||
|
async findTermMeta(term, titles) {
|
||||||
|
if (!this.db) {
|
||||||
|
throw 'Database not initialized';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const results = [];
|
||||||
|
await this.db.termMeta.where('expression').equals(term).each(row => {
|
||||||
|
if (titles.includes(row.dictionary)) {
|
||||||
|
results.push({
|
||||||
|
mode: row.mode,
|
||||||
|
data: row.data,
|
||||||
|
dictionary: row.dictionary
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
async findKanji(kanji, titles) {
|
async findKanji(kanji, titles) {
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
return Promise.reject('database not initialized');
|
throw 'Database not initialized';
|
||||||
}
|
}
|
||||||
|
|
||||||
const results = [];
|
const results = [];
|
||||||
@ -111,69 +114,199 @@ class Database {
|
|||||||
kunyomi: dictFieldSplit(row.kunyomi),
|
kunyomi: dictFieldSplit(row.kunyomi),
|
||||||
tags: dictFieldSplit(row.tags),
|
tags: dictFieldSplit(row.tags),
|
||||||
glossary: row.meanings,
|
glossary: row.meanings,
|
||||||
|
stats: row.stats,
|
||||||
dictionary: row.dictionary
|
dictionary: row.dictionary
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.cacheTagMeta(titles);
|
return results;
|
||||||
for (const result of results) {
|
}
|
||||||
result.tagMeta = this.tagCache[result.dictionary] || {};
|
|
||||||
|
async findKanjiMeta(kanji, titles) {
|
||||||
|
if (!this.db) {
|
||||||
|
throw 'Database not initialized';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const results = [];
|
||||||
|
await this.db.kanjiMeta.where('character').equals(kanji).each(row => {
|
||||||
|
if (titles.includes(row.dictionary)) {
|
||||||
|
results.push({
|
||||||
|
mode: row.mode,
|
||||||
|
data: row.data,
|
||||||
|
dictionary: row.dictionary
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
async cacheTagMeta(titles) {
|
async findTagForTitle(name, title) {
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
throw 'database not initialized';
|
throw 'Database not initialized';
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const title of titles) {
|
this.tagCache[title] = this.tagCache[title] || {};
|
||||||
if (!this.tagCache[title]) {
|
|
||||||
const tagMeta = {};
|
|
||||||
await this.db.tagMeta.where('dictionary').equals(title).each(row => {
|
|
||||||
tagMeta[row.name] = {category: row.category, notes: row.notes, order: row.order};
|
|
||||||
});
|
|
||||||
|
|
||||||
this.tagCache[title] = tagMeta;
|
let result = this.tagCache[title][name];
|
||||||
}
|
if (!result) {
|
||||||
|
await this.db.tagMeta.where('name').equals(name).each(row => {
|
||||||
|
if (title === row.dictionary) {
|
||||||
|
result = row;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.tagCache[title][name] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getDictionaries() {
|
async getTitles() {
|
||||||
if (this.db) {
|
if (this.db) {
|
||||||
return this.db.dictionaries.toArray();
|
return this.db.dictionaries.toArray();
|
||||||
} else {
|
} else {
|
||||||
throw 'database not initialized';
|
throw 'Database not initialized';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async importDictionary(archive, callback) {
|
async importDictionary(archive, callback) {
|
||||||
if (!this.db) {
|
if (!this.db) {
|
||||||
return Promise.reject('database not initialized');
|
throw 'Database not initialized';
|
||||||
}
|
}
|
||||||
|
|
||||||
let summary = null;
|
const indexDataLoaded = async summary => {
|
||||||
const indexLoaded = async (title, version, revision, tagMeta, hasTerms, hasKanji) => {
|
if (summary.version > 2) {
|
||||||
summary = {title, version, revision, hasTerms, hasKanji};
|
throw 'Unsupported dictionary version';
|
||||||
|
|
||||||
const count = await this.db.dictionaries.where('title').equals(title).count();
|
|
||||||
if (count > 0) {
|
|
||||||
throw `dictionary "${title}" is already imported`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.db.dictionaries.add({title, version, revision, hasTerms, hasKanji});
|
const count = await this.db.dictionaries.where('title').equals(summary.title).count();
|
||||||
|
if (count > 0) {
|
||||||
|
throw 'Dictionary is already imported';
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.db.dictionaries.add(summary);
|
||||||
|
};
|
||||||
|
|
||||||
|
const termDataLoaded = async (summary, entries, total, current) => {
|
||||||
|
if (callback) {
|
||||||
|
callback(total, current);
|
||||||
|
}
|
||||||
|
|
||||||
const rows = [];
|
const rows = [];
|
||||||
for (const tag in tagMeta || {}) {
|
if (summary.version === 1) {
|
||||||
const meta = tagMeta[tag];
|
for (const [expression, reading, tags, rules, score, ...glossary] of entries) {
|
||||||
|
rows.push({
|
||||||
|
expression,
|
||||||
|
reading,
|
||||||
|
tags,
|
||||||
|
rules,
|
||||||
|
score,
|
||||||
|
glossary,
|
||||||
|
dictionary: summary.title
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const [expression, reading, tags, rules, score, glossary] of entries) {
|
||||||
|
rows.push({
|
||||||
|
expression,
|
||||||
|
reading,
|
||||||
|
tags,
|
||||||
|
rules,
|
||||||
|
score,
|
||||||
|
glossary,
|
||||||
|
dictionary: summary.title
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.db.terms.bulkAdd(rows);
|
||||||
|
};
|
||||||
|
|
||||||
|
const termMetaDataLoaded = async (summary, entries, total, current) => {
|
||||||
|
if (callback) {
|
||||||
|
callback(total, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rows = [];
|
||||||
|
for (const [expression, mode, data] of entries) {
|
||||||
|
rows.push({
|
||||||
|
expression,
|
||||||
|
mode,
|
||||||
|
data,
|
||||||
|
dictionary: summary.title
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.db.termMeta.bulkAdd(rows);
|
||||||
|
};
|
||||||
|
|
||||||
|
const kanjiDataLoaded = async (summary, entries, total, current) => {
|
||||||
|
if (callback) {
|
||||||
|
callback(total, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rows = [];
|
||||||
|
if (summary.version === 1) {
|
||||||
|
for (const [character, onyomi, kunyomi, tags, ...meanings] of entries) {
|
||||||
|
rows.push({
|
||||||
|
character,
|
||||||
|
onyomi,
|
||||||
|
kunyomi,
|
||||||
|
tags,
|
||||||
|
meanings,
|
||||||
|
dictionary: summary.title
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (const [character, onyomi, kunyomi, tags, meanings, stats] of entries) {
|
||||||
|
rows.push({
|
||||||
|
character,
|
||||||
|
onyomi,
|
||||||
|
kunyomi,
|
||||||
|
tags,
|
||||||
|
meanings,
|
||||||
|
stats,
|
||||||
|
dictionary: summary.title
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.db.kanji.bulkAdd(rows);
|
||||||
|
};
|
||||||
|
|
||||||
|
const kanjiMetaDataLoaded = async (summary, entries, total, current) => {
|
||||||
|
if (callback) {
|
||||||
|
callback(total, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rows = [];
|
||||||
|
for (const [character, mode, data] of entries) {
|
||||||
|
rows.push({
|
||||||
|
character,
|
||||||
|
mode,
|
||||||
|
data,
|
||||||
|
dictionary: summary.title
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.db.kanjiMeta.bulkAdd(rows);
|
||||||
|
};
|
||||||
|
|
||||||
|
const tagDataLoaded = async (summary, entries, total, current) => {
|
||||||
|
if (callback) {
|
||||||
|
callback(total, current);
|
||||||
|
}
|
||||||
|
|
||||||
|
const rows = [];
|
||||||
|
for (const [name, category, order, notes] of entries) {
|
||||||
const row = dictTagSanitize({
|
const row = dictTagSanitize({
|
||||||
name: tag,
|
name,
|
||||||
category: meta.category,
|
category,
|
||||||
notes: meta.notes,
|
order,
|
||||||
order: meta.order,
|
notes,
|
||||||
dictionary: title
|
dictionary: summary.title
|
||||||
});
|
});
|
||||||
|
|
||||||
rows.push(row);
|
rows.push(row);
|
||||||
@ -182,94 +315,103 @@ class Database {
|
|||||||
await this.db.tagMeta.bulkAdd(rows);
|
await this.db.tagMeta.bulkAdd(rows);
|
||||||
};
|
};
|
||||||
|
|
||||||
const termsLoaded = async (title, entries, total, current) => {
|
return await Database.importDictionaryZip(
|
||||||
if (callback) {
|
archive,
|
||||||
callback(total, current);
|
indexDataLoaded,
|
||||||
}
|
termDataLoaded,
|
||||||
|
termMetaDataLoaded,
|
||||||
const rows = [];
|
kanjiDataLoaded,
|
||||||
for (const [expression, reading, tags, rules, score, ...glossary] of entries) {
|
kanjiMetaDataLoaded,
|
||||||
rows.push({
|
tagDataLoaded
|
||||||
expression,
|
);
|
||||||
reading,
|
|
||||||
tags,
|
|
||||||
rules,
|
|
||||||
score,
|
|
||||||
glossary,
|
|
||||||
dictionary: title
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.db.terms.bulkAdd(rows);
|
|
||||||
};
|
|
||||||
|
|
||||||
const kanjiLoaded = async (title, entries, total, current) => {
|
|
||||||
if (callback) {
|
|
||||||
callback(total, current);
|
|
||||||
}
|
|
||||||
|
|
||||||
const rows = [];
|
|
||||||
for (const [character, onyomi, kunyomi, tags, ...meanings] of entries) {
|
|
||||||
rows.push({
|
|
||||||
character,
|
|
||||||
onyomi,
|
|
||||||
kunyomi,
|
|
||||||
tags,
|
|
||||||
meanings,
|
|
||||||
dictionary: title
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await this.db.kanji.bulkAdd(rows);
|
|
||||||
};
|
|
||||||
|
|
||||||
await Database.importDictionaryZip(archive, indexLoaded, termsLoaded, kanjiLoaded);
|
|
||||||
return summary;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async importDictionaryZip(archive, indexLoaded, termsLoaded, kanjiLoaded) {
|
static async importDictionaryZip(
|
||||||
const files = (await JSZip.loadAsync(archive)).files;
|
archive,
|
||||||
|
indexDataLoaded,
|
||||||
|
termDataLoaded,
|
||||||
|
termMetaDataLoaded,
|
||||||
|
kanjiDataLoaded,
|
||||||
|
kanjiMetaDataLoaded,
|
||||||
|
tagDataLoaded
|
||||||
|
) {
|
||||||
|
const zip = await JSZip.loadAsync(archive);
|
||||||
|
|
||||||
const indexFile = files['index.json'];
|
const indexFile = zip.files['index.json'];
|
||||||
if (!indexFile) {
|
if (!indexFile) {
|
||||||
throw 'no dictionary index found in archive';
|
throw 'No dictionary index found in archive';
|
||||||
}
|
}
|
||||||
|
|
||||||
const index = JSON.parse(await indexFile.async('string'));
|
const index = JSON.parse(await indexFile.async('string'));
|
||||||
if (!index.title || !index.version || !index.revision) {
|
if (!index.title || !index.revision) {
|
||||||
throw 'unrecognized dictionary format';
|
throw 'Unrecognized dictionary format';
|
||||||
}
|
}
|
||||||
|
|
||||||
await indexLoaded(
|
const summary = {
|
||||||
index.title,
|
title: index.title,
|
||||||
index.version,
|
revision: index.revision,
|
||||||
index.revision,
|
version: index.format || index.version
|
||||||
index.tagMeta || {},
|
};
|
||||||
index.termBanks > 0,
|
|
||||||
index.kanjiBanks > 0
|
|
||||||
);
|
|
||||||
|
|
||||||
const banksTotal = index.termBanks + index.kanjiBanks;
|
if (indexDataLoaded) {
|
||||||
let banksLoaded = 0;
|
await indexDataLoaded(summary);
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 1; i <= index.termBanks; ++i) {
|
const buildTermBankName = index => `term_bank_${index + 1}.json`;
|
||||||
const bankFile = files[`term_bank_${i}.json`];
|
const buildTermMetaBankName = index => `term_meta_bank_${index + 1}.json`;
|
||||||
if (bankFile) {
|
const buildKanjiBankName = index => `kanji_bank_${index + 1}.json`;
|
||||||
const bank = JSON.parse(await bankFile.async('string'));
|
const buildKanjiMetaBankName = index => `kanji_meta_bank_${index + 1}.json`;
|
||||||
await termsLoaded(index.title, bank, banksTotal, banksLoaded++);
|
const buildTagBankName = index => `tag_bank_${index + 1}.json`;
|
||||||
} else {
|
|
||||||
throw 'missing term bank file';
|
const countBanks = namer => {
|
||||||
|
let count = 0;
|
||||||
|
while (zip.files[namer(count)]) {
|
||||||
|
++count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
};
|
||||||
|
|
||||||
|
const termBankCount = countBanks(buildTermBankName);
|
||||||
|
const termMetaBankCount = countBanks(buildTermMetaBankName);
|
||||||
|
const kanjiBankCount = countBanks(buildKanjiBankName);
|
||||||
|
const kanjiMetaBankCount = countBanks(buildKanjiMetaBankName);
|
||||||
|
const tagBankCount = countBanks(buildTagBankName);
|
||||||
|
|
||||||
|
let bankLoadedCount = 0;
|
||||||
|
let bankTotalCount =
|
||||||
|
termBankCount +
|
||||||
|
termMetaBankCount +
|
||||||
|
kanjiBankCount +
|
||||||
|
kanjiMetaBankCount +
|
||||||
|
tagBankCount;
|
||||||
|
|
||||||
|
if (tagDataLoaded && index.tagMeta) {
|
||||||
|
const bank = [];
|
||||||
|
for (const name in index.tagMeta) {
|
||||||
|
const tag = index.tagMeta[name];
|
||||||
|
bank.push([name, tag.category, tag.order, tag.notes]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tagDataLoaded(summary, bank, ++bankTotalCount, bankLoadedCount++);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 1; i <= index.kanjiBanks; ++i) {
|
const loadBank = async (summary, namer, count, callback) => {
|
||||||
const bankFile = files[`kanji_bank_${i}.json`];
|
if (callback) {
|
||||||
if (bankFile) {
|
for (let i = 0; i < count; ++i) {
|
||||||
const bank = JSON.parse(await bankFile.async('string'));
|
const bankFile = zip.files[namer(i)];
|
||||||
await kanjiLoaded(index.title, bank, banksTotal, banksLoaded++);
|
const bank = JSON.parse(await bankFile.async('string'));
|
||||||
} else {
|
await callback(summary, bank, bankTotalCount, bankLoadedCount++);
|
||||||
throw 'missing kanji bank file';
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
await loadBank(summary, buildTermBankName, termBankCount, termDataLoaded);
|
||||||
|
await loadBank(summary, buildTermMetaBankName, termMetaBankCount, termMetaDataLoaded);
|
||||||
|
await loadBank(summary, buildKanjiBankName, kanjiBankCount, kanjiDataLoaded);
|
||||||
|
await loadBank(summary, buildKanjiMetaBankName, kanjiMetaBankCount, kanjiMetaDataLoaded);
|
||||||
|
await loadBank(summary, buildTagBankName, tagBankCount, tagDataLoaded);
|
||||||
|
|
||||||
|
return summary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,14 +55,6 @@ function dictRowsSort(rows, options) {
|
|||||||
|
|
||||||
function dictTermsSort(definitions, dictionaries=null) {
|
function dictTermsSort(definitions, dictionaries=null) {
|
||||||
return definitions.sort((v1, v2) => {
|
return definitions.sort((v1, v2) => {
|
||||||
const sl1 = v1.source.length;
|
|
||||||
const sl2 = v2.source.length;
|
|
||||||
if (sl1 > sl2) {
|
|
||||||
return -1;
|
|
||||||
} else if (sl1 < sl2) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dictionaries !== null) {
|
if (dictionaries !== null) {
|
||||||
const p1 = (dictionaries[v1.dictionary] || {}).priority || 0;
|
const p1 = (dictionaries[v1.dictionary] || {}).priority || 0;
|
||||||
const p2 = (dictionaries[v2.dictionary] || {}).priority || 0;
|
const p2 = (dictionaries[v2.dictionary] || {}).priority || 0;
|
||||||
@ -73,11 +65,11 @@ function dictTermsSort(definitions, dictionaries=null) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const s1 = v1.score;
|
const sl1 = v1.source.length;
|
||||||
const s2 = v2.score;
|
const sl2 = v2.source.length;
|
||||||
if (s1 > s2) {
|
if (sl1 > sl2) {
|
||||||
return -1;
|
return -1;
|
||||||
} else if (s1 < s2) {
|
} else if (sl1 < sl2) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +81,14 @@ function dictTermsSort(definitions, dictionaries=null) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const s1 = v1.score;
|
||||||
|
const s2 = v2.score;
|
||||||
|
if (s1 > s2) {
|
||||||
|
return -1;
|
||||||
|
} else if (s1 < s2) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return v2.expression.localeCompare(v1.expression);
|
return v2.expression.localeCompare(v1.expression);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -148,16 +148,6 @@ function dictTagBuildSource(name) {
|
|||||||
return dictTagSanitize({name, category: 'dictionary', order: 100});
|
return dictTagSanitize({name, category: 'dictionary', order: 100});
|
||||||
}
|
}
|
||||||
|
|
||||||
function dictTagBuild(name, meta) {
|
|
||||||
const tag = {name};
|
|
||||||
const symbol = name.split(':')[0];
|
|
||||||
for (const prop in meta[symbol] || {}) {
|
|
||||||
tag[prop] = meta[symbol][prop];
|
|
||||||
}
|
|
||||||
|
|
||||||
return dictTagSanitize(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
function dictTagSanitize(tag) {
|
function dictTagSanitize(tag) {
|
||||||
tag.name = tag.name || 'untitled';
|
tag.name = tag.name || 'untitled';
|
||||||
tag.category = tag.category || 'default';
|
tag.category = tag.category || 'default';
|
||||||
|
@ -146,7 +146,8 @@ function optionsSetDefaults(options) {
|
|||||||
middleMouse: true,
|
middleMouse: true,
|
||||||
selectText: true,
|
selectText: true,
|
||||||
alphanumeric: true,
|
alphanumeric: true,
|
||||||
delay: 15,
|
autoHideResults: false,
|
||||||
|
delay: 20,
|
||||||
length: 10,
|
length: 10,
|
||||||
modifier: 'shift'
|
modifier: 'shift'
|
||||||
},
|
},
|
||||||
|
@ -22,7 +22,7 @@ function requestJson(url, action, params) {
|
|||||||
const xhr = new XMLHttpRequest();
|
const xhr = new XMLHttpRequest();
|
||||||
xhr.overrideMimeType('application/json');
|
xhr.overrideMimeType('application/json');
|
||||||
xhr.addEventListener('load', () => resolve(xhr.responseText));
|
xhr.addEventListener('load', () => resolve(xhr.responseText));
|
||||||
xhr.addEventListener('error', () => reject('failed to execute network request'));
|
xhr.addEventListener('error', () => reject('Failed to connect'));
|
||||||
xhr.open(action, url);
|
xhr.open(action, url);
|
||||||
if (params) {
|
if (params) {
|
||||||
xhr.send(JSON.stringify(params));
|
xhr.send(JSON.stringify(params));
|
||||||
@ -34,7 +34,7 @@ function requestJson(url, action, params) {
|
|||||||
return JSON.parse(responseText);
|
return JSON.parse(responseText);
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
return Promise.reject('invalid JSON response');
|
return Promise.reject('Invalid response');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ class DisplaySearch extends Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onError(error) {
|
onError(error) {
|
||||||
window.alert(`Error: ${error}`);
|
window.alert(`Error: ${error.toString ? error.toString() : error}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearchClear() {
|
onSearchClear() {
|
||||||
|
@ -35,6 +35,7 @@ async function formRead() {
|
|||||||
optionsNew.scanning.middleMouse = $('#middle-mouse-button-scan').prop('checked');
|
optionsNew.scanning.middleMouse = $('#middle-mouse-button-scan').prop('checked');
|
||||||
optionsNew.scanning.selectText = $('#select-matched-text').prop('checked');
|
optionsNew.scanning.selectText = $('#select-matched-text').prop('checked');
|
||||||
optionsNew.scanning.alphanumeric = $('#search-alphanumeric').prop('checked');
|
optionsNew.scanning.alphanumeric = $('#search-alphanumeric').prop('checked');
|
||||||
|
optionsNew.scanning.autoHideResults = $('#auto-hide-results').prop('checked');
|
||||||
optionsNew.scanning.delay = parseInt($('#scan-delay').val(), 10);
|
optionsNew.scanning.delay = parseInt($('#scan-delay').val(), 10);
|
||||||
optionsNew.scanning.length = parseInt($('#scan-length').val(), 10);
|
optionsNew.scanning.length = parseInt($('#scan-length').val(), 10);
|
||||||
optionsNew.scanning.modifier = $('#scan-modifier-key').val();
|
optionsNew.scanning.modifier = $('#scan-modifier-key').val();
|
||||||
@ -82,7 +83,9 @@ function formUpdateVisibility(options) {
|
|||||||
|
|
||||||
const debug = $('#debug');
|
const debug = $('#debug');
|
||||||
if (options.general.debugInfo) {
|
if (options.general.debugInfo) {
|
||||||
const text = JSON.stringify(options, null, 4);
|
const temp = utilIsolate(options);
|
||||||
|
temp.anki.fieldTemplates = '...';
|
||||||
|
const text = JSON.stringify(temp, null, 4);
|
||||||
debug.html(handlebarsEscape(text));
|
debug.html(handlebarsEscape(text));
|
||||||
debug.show();
|
debug.show();
|
||||||
} else {
|
} else {
|
||||||
@ -134,11 +137,12 @@ async function onReady() {
|
|||||||
$('#middle-mouse-button-scan').prop('checked', options.scanning.middleMouse);
|
$('#middle-mouse-button-scan').prop('checked', options.scanning.middleMouse);
|
||||||
$('#select-matched-text').prop('checked', options.scanning.selectText);
|
$('#select-matched-text').prop('checked', options.scanning.selectText);
|
||||||
$('#search-alphanumeric').prop('checked', options.scanning.alphanumeric);
|
$('#search-alphanumeric').prop('checked', options.scanning.alphanumeric);
|
||||||
|
$('#auto-hide-results').prop('checked', options.scanning.autoHideResults);
|
||||||
$('#scan-delay').val(options.scanning.delay);
|
$('#scan-delay').val(options.scanning.delay);
|
||||||
$('#scan-length').val(options.scanning.length);
|
$('#scan-length').val(options.scanning.length);
|
||||||
$('#scan-modifier-key').val(options.scanning.modifier);
|
$('#scan-modifier-key').val(options.scanning.modifier);
|
||||||
|
|
||||||
$('#dict-purge').click(utilAsync(onDictionaryPurge));
|
$('#dict-purge-link').click(utilAsync(onDictionaryPurge));
|
||||||
$('#dict-file').change(utilAsync(onDictionaryImport));
|
$('#dict-file').change(utilAsync(onDictionaryImport));
|
||||||
|
|
||||||
$('#anki-enable').prop('checked', options.anki.enable);
|
$('#anki-enable').prop('checked', options.anki.enable);
|
||||||
@ -175,7 +179,33 @@ $(document).ready(utilAsync(onReady));
|
|||||||
function dictionaryErrorShow(error) {
|
function dictionaryErrorShow(error) {
|
||||||
const dialog = $('#dict-error');
|
const dialog = $('#dict-error');
|
||||||
if (error) {
|
if (error) {
|
||||||
dialog.show().find('span').text(error);
|
const overrides = [
|
||||||
|
[
|
||||||
|
'A mutation operation was attempted on a database that did not allow mutations.',
|
||||||
|
'Access to IndexedDB appears to be restricted. Firefox seems to require that the history preference is set to "Remember history" before IndexedDB use of any kind is allowed.'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'The operation failed for reasons unrelated to the database itself and not covered by any other error code.',
|
||||||
|
'Unable to access IndexedDB due to a possibly corrupt user profile. Try using the "Refresh Firefox" feature to reset your user profile.'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'BulkError',
|
||||||
|
'Unable to finish importing dictionary data into IndexedDB. This may indicate that you do not have sufficient disk space available to complete this operation.'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
if (error.toString) {
|
||||||
|
error = error.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [match, subst] of overrides) {
|
||||||
|
if (error.includes(match)) {
|
||||||
|
error = subst;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show().text(error);
|
||||||
} else {
|
} else {
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
}
|
}
|
||||||
@ -211,7 +241,7 @@ async function dictionaryGroupsPopulate(options) {
|
|||||||
const dictGroups = $('#dict-groups').empty();
|
const dictGroups = $('#dict-groups').empty();
|
||||||
const dictWarning = $('#dict-warning').hide();
|
const dictWarning = $('#dict-warning').hide();
|
||||||
|
|
||||||
const dictRows = await utilDatabaseGetDictionaries();
|
const dictRows = await utilDatabaseGetTitles();
|
||||||
if (dictRows.length === 0) {
|
if (dictRows.length === 0) {
|
||||||
dictWarning.show();
|
dictWarning.show();
|
||||||
}
|
}
|
||||||
@ -241,7 +271,7 @@ async function onDictionaryPurge(e) {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
const dictControls = $('#dict-importer, #dict-groups').hide();
|
const dictControls = $('#dict-importer, #dict-groups').hide();
|
||||||
const dictProgress = $('#dict-purge-progress').show();
|
const dictProgress = $('#dict-purge').show();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
dictionaryErrorShow();
|
dictionaryErrorShow();
|
||||||
@ -310,7 +340,7 @@ function ankiSpinnerShow(show) {
|
|||||||
function ankiErrorShow(error) {
|
function ankiErrorShow(error) {
|
||||||
const dialog = $('#anki-error');
|
const dialog = $('#anki-error');
|
||||||
if (error) {
|
if (error) {
|
||||||
dialog.show().find('span').text(error);
|
dialog.show().text(error);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
|
@ -22,38 +22,87 @@ templates['dictionary.html'] = template({"1":function(container,depth0,helpers,p
|
|||||||
+ "\" class=\"form-control dict-priority\">\n </div>\n</div>\n";
|
+ "\" class=\"form-control dict-priority\">\n </div>\n</div>\n";
|
||||||
},"useData":true});
|
},"useData":true});
|
||||||
templates['kanji.html'] = template({"1":function(container,depth0,helpers,partials,data) {
|
templates['kanji.html'] = template({"1":function(container,depth0,helpers,partials,data) {
|
||||||
|
var stack1;
|
||||||
|
|
||||||
|
return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.data : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.program(8, data, 0),"data":data})) != null ? stack1 : "");
|
||||||
|
},"2":function(container,depth0,helpers,partials,data) {
|
||||||
|
var stack1;
|
||||||
|
|
||||||
|
return "<table class=\"info-output\">\n"
|
||||||
|
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.data : depth0),{"name":"each","hash":{},"fn":container.program(3, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
|
+ "</table>\n";
|
||||||
|
},"3":function(container,depth0,helpers,partials,data) {
|
||||||
|
var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {});
|
||||||
|
|
||||||
|
return " <tr>\n <th>"
|
||||||
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.notes : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.program(6, data, 0),"data":data})) != null ? stack1 : "")
|
||||||
|
+ "</th>\n <td>"
|
||||||
|
+ container.escapeExpression(((helper = (helper = helpers.value || (depth0 != null ? depth0.value : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"value","hash":{},"data":data}) : helper)))
|
||||||
|
+ "</td>\n </tr>\n";
|
||||||
|
},"4":function(container,depth0,helpers,partials,data) {
|
||||||
|
var helper;
|
||||||
|
|
||||||
|
return container.escapeExpression(((helper = (helper = helpers.notes || (depth0 != null ? depth0.notes : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"notes","hash":{},"data":data}) : helper)));
|
||||||
|
},"6":function(container,depth0,helpers,partials,data) {
|
||||||
|
var helper;
|
||||||
|
|
||||||
|
return container.escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),{"name":"name","hash":{},"data":data}) : helper)));
|
||||||
|
},"8":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "No data found\n";
|
||||||
|
},"10":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {});
|
var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {});
|
||||||
|
|
||||||
return "<div class=\"entry\" data-type=\"kanji\">\n <div class=\"actions\">\n"
|
return "<div class=\"entry\" data-type=\"kanji\">\n <div class=\"actions\">\n"
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(2, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.addable : depth0),{"name":"if","hash":{},"fn":container.program(11, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.source : depth0),{"name":"if","hash":{},"fn":container.program(4, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.source : depth0),{"name":"if","hash":{},"fn":container.program(13, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ " <img src=\"/mixed/img/entry-current.png\" class=\"current\" title=\"Current entry (Alt + Up/Down/Home/End/PgUp/PgDn)\" alt>\n </div>\n\n <div class=\"glyph\">"
|
+ " <img src=\"/mixed/img/entry-current.png\" class=\"current\" title=\"Current entry (Alt + Up/Down/Home/End/PgUp/PgDn)\" alt>\n </div>\n\n <div class=\"glyph\">"
|
||||||
+ container.escapeExpression(((helper = (helper = helpers.character || (depth0 != null ? depth0.character : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"character","hash":{},"data":data}) : helper)))
|
+ container.escapeExpression(((helper = (helper = helpers.character || (depth0 != null ? depth0.character : depth0)) != null ? helper : helpers.helperMissing),(typeof helper === "function" ? helper.call(alias1,{"name":"character","hash":{},"data":data}) : helper)))
|
||||||
+ "</div>\n\n <div class=\"reading\">\n <table>\n <tr>\n <th>Kunyomi:</th>\n <td>\n"
|
+ "</div>\n\n"
|
||||||
+ ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.kunyomi : depth0),{"name":"each","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.frequencies : depth0),{"name":"if","hash":{},"fn":container.program(15, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ " </td>\n </tr>\n <tr>\n <th>Onyomi:</th>\n <td>\n"
|
+ "\n"
|
||||||
+ ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.onyomi : depth0),{"name":"each","hash":{},"fn":container.program(6, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.tags : depth0),{"name":"if","hash":{},"fn":container.program(18, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ " </td>\n </tr>\n </table>\n </div>\n\n <div>\n"
|
+ "\n <table class=\"table table-condensed glyph-data\">\n <tr>\n <th>Glossary</th>\n <th>Readings</th>\n <th>Statistics</th>\n </tr>\n <tr>\n <td class=\"glossary\">\n"
|
||||||
+ ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(9, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(21, data, 0),"inverse":container.program(24, data, 0),"data":data})) != null ? stack1 : "")
|
||||||
+ " </div>\n\n <div class=\"glossary\">\n"
|
+ " </td>\n <td class=\"reading\">\n "
|
||||||
+ ((stack1 = helpers["if"].call(alias1,((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(11, data, 0),"inverse":container.program(15, data, 0),"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.onyomi : depth0),{"name":"if","hash":{},"fn":container.program(26, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ " </div>\n\n"
|
+ "\n "
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(18, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.kunyomi : depth0),{"name":"if","hash":{},"fn":container.program(29, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
|
+ "\n </td>\n <td>"
|
||||||
|
+ ((stack1 = container.invokePartial(partials.table,depth0,{"name":"table","hash":{"data":((stack1 = (depth0 != null ? depth0.stats : depth0)) != null ? stack1.misc : stack1)},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "")
|
||||||
|
+ "</td>\n </tr>\n <tr>\n <th colspan=\"3\">Classifications</th>\n </tr>\n <tr>\n <td colspan=\"3\">"
|
||||||
|
+ ((stack1 = container.invokePartial(partials.table,depth0,{"name":"table","hash":{"data":((stack1 = (depth0 != null ? depth0.stats : depth0)) != null ? stack1["class"] : stack1)},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "")
|
||||||
|
+ "</td>\n </tr>\n <tr>\n <th colspan=\"3\">Codepoints</th>\n </tr>\n <tr>\n <td colspan=\"3\">"
|
||||||
|
+ ((stack1 = container.invokePartial(partials.table,depth0,{"name":"table","hash":{"data":((stack1 = (depth0 != null ? depth0.stats : depth0)) != null ? stack1.code : stack1)},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "")
|
||||||
|
+ "</td>\n </tr>\n <tr>\n <th colspan=\"3\">Dictionary Indices</th>\n </tr>\n <tr>\n <td colspan=\"3\">"
|
||||||
|
+ ((stack1 = container.invokePartial(partials.table,depth0,{"name":"table","hash":{"data":((stack1 = (depth0 != null ? depth0.stats : depth0)) != null ? stack1.index : stack1)},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "")
|
||||||
|
+ "</td>\n </tr>\n </table>\n\n"
|
||||||
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(31, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ "</div>\n";
|
+ "</div>\n";
|
||||||
},"2":function(container,depth0,helpers,partials,data) {
|
},"11":function(container,depth0,helpers,partials,data) {
|
||||||
return " <a href=\"#\" class=\"action-view-note pending disabled\"><img src=\"/mixed/img/view-note.png\" title=\"View added note (Alt + V)\" alt></a>\n <a href=\"#\" class=\"action-add-note pending disabled\" data-mode=\"kanji\"><img src=\"/mixed/img/add-kanji.png\" title=\"Add Kanji (Alt + K)\" alt></a>\n";
|
return " <a href=\"#\" class=\"action-view-note pending disabled\"><img src=\"/mixed/img/view-note.png\" title=\"View added note (Alt + V)\" alt></a>\n <a href=\"#\" class=\"action-add-note pending disabled\" data-mode=\"kanji\"><img src=\"/mixed/img/add-kanji.png\" title=\"Add Kanji (Alt + K)\" alt></a>\n";
|
||||||
},"4":function(container,depth0,helpers,partials,data) {
|
},"13":function(container,depth0,helpers,partials,data) {
|
||||||
return " <a href=\"#\" class=\"source-term\"><img src=\"/mixed/img/source-term.png\" title=\"Source term (Alt + B)\" alt></a>\n";
|
return " <a href=\"#\" class=\"source-term\"><img src=\"/mixed/img/source-term.png\" title=\"Source term (Alt + B)\" alt></a>\n";
|
||||||
},"6":function(container,depth0,helpers,partials,data) {
|
},"15":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return " "
|
return " <div>\n"
|
||||||
+ container.escapeExpression(container.lambda(depth0, depth0))
|
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(16, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.last),{"name":"unless","hash":{},"fn":container.program(7, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ " </div>\n";
|
||||||
+ "\n";
|
},"16":function(container,depth0,helpers,partials,data) {
|
||||||
},"7":function(container,depth0,helpers,partials,data) {
|
var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;
|
||||||
return ", ";
|
|
||||||
},"9":function(container,depth0,helpers,partials,data) {
|
return " <span class=\"label label-default tag-frequency\">"
|
||||||
|
+ alias4(((helper = (helper = helpers.dictionary || (depth0 != null ? depth0.dictionary : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"dictionary","hash":{},"data":data}) : helper)))
|
||||||
|
+ ":"
|
||||||
|
+ alias4(((helper = (helper = helpers.frequency || (depth0 != null ? depth0.frequency : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"frequency","hash":{},"data":data}) : helper)))
|
||||||
|
+ "</span>\n";
|
||||||
|
},"18":function(container,depth0,helpers,partials,data) {
|
||||||
|
var stack1;
|
||||||
|
|
||||||
|
return " <div>\n"
|
||||||
|
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.tags : depth0),{"name":"each","hash":{},"fn":container.program(19, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
|
+ " </div>\n";
|
||||||
|
},"19":function(container,depth0,helpers,partials,data) {
|
||||||
var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;
|
var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;
|
||||||
|
|
||||||
return " <span class=\"label label-default tag-"
|
return " <span class=\"label label-default tag-"
|
||||||
@ -63,67 +112,74 @@ templates['kanji.html'] = template({"1":function(container,depth0,helpers,partia
|
|||||||
+ "\">"
|
+ "\">"
|
||||||
+ alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper)))
|
+ alias4(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper)))
|
||||||
+ "</span>\n";
|
+ "</span>\n";
|
||||||
},"11":function(container,depth0,helpers,partials,data) {
|
},"21":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return " <ol>\n"
|
return " <ol>"
|
||||||
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.glossary : depth0),{"name":"each","hash":{},"fn":container.program(12, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.glossary : depth0),{"name":"each","hash":{},"fn":container.program(22, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ " </ol>\n";
|
+ "</ol>\n";
|
||||||
},"12":function(container,depth0,helpers,partials,data) {
|
},"22":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1, helper, options, buffer =
|
return "<li><span class=\"glossary-item\">"
|
||||||
" <li><span class=\"glossary-item\">";
|
+ container.escapeExpression(container.lambda(depth0, depth0))
|
||||||
stack1 = ((helper = (helper = helpers.multiLine || (depth0 != null ? depth0.multiLine : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"multiLine","hash":{},"fn":container.program(13, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
|
+ "</span></li>";
|
||||||
if (!helpers.multiLine) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
|
},"24":function(container,depth0,helpers,partials,data) {
|
||||||
if (stack1 != null) { buffer += stack1; }
|
|
||||||
return buffer + "</span></li>\n";
|
|
||||||
},"13":function(container,depth0,helpers,partials,data) {
|
|
||||||
return container.escapeExpression(container.lambda(depth0, depth0));
|
|
||||||
},"15":function(container,depth0,helpers,partials,data) {
|
|
||||||
var stack1, helper, options, buffer =
|
|
||||||
" <div class=\"glossary-item\">";
|
|
||||||
stack1 = ((helper = (helper = helpers.multiLine || (depth0 != null ? depth0.multiLine : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"multiLine","hash":{},"fn":container.program(16, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
|
|
||||||
if (!helpers.multiLine) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
|
|
||||||
if (stack1 != null) { buffer += stack1; }
|
|
||||||
return buffer + "</div>\n";
|
|
||||||
},"16":function(container,depth0,helpers,partials,data) {
|
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["0"] : stack1), depth0));
|
return " <span class=\"glossary-item\">"
|
||||||
},"18":function(container,depth0,helpers,partials,data) {
|
+ container.escapeExpression(container.lambda(((stack1 = (depth0 != null ? depth0.glossary : depth0)) != null ? stack1["0"] : stack1), depth0))
|
||||||
|
+ "</span>\n";
|
||||||
|
},"26":function(container,depth0,helpers,partials,data) {
|
||||||
|
var stack1;
|
||||||
|
|
||||||
|
return "<dl>"
|
||||||
|
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.onyomi : depth0),{"name":"each","hash":{},"fn":container.program(27, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
|
+ "</dl>";
|
||||||
|
},"27":function(container,depth0,helpers,partials,data) {
|
||||||
|
return "<dd>"
|
||||||
|
+ container.escapeExpression(container.lambda(depth0, depth0))
|
||||||
|
+ "</dd>";
|
||||||
|
},"29":function(container,depth0,helpers,partials,data) {
|
||||||
|
var stack1;
|
||||||
|
|
||||||
|
return "<dl>"
|
||||||
|
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.kunyomi : depth0),{"name":"each","hash":{},"fn":container.program(27, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
|
+ "</dl>";
|
||||||
|
},"31":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1, helper, options, buffer =
|
var stack1, helper, options, buffer =
|
||||||
" <pre>";
|
" <pre>";
|
||||||
stack1 = ((helper = (helper = helpers.dumpObject || (depth0 != null ? depth0.dumpObject : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"dumpObject","hash":{},"fn":container.program(19, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
|
stack1 = ((helper = (helper = helpers.dumpObject || (depth0 != null ? depth0.dumpObject : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"dumpObject","hash":{},"fn":container.program(32, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
|
||||||
if (!helpers.dumpObject) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
|
if (!helpers.dumpObject) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
|
||||||
if (stack1 != null) { buffer += stack1; }
|
if (stack1 != null) { buffer += stack1; }
|
||||||
return buffer + "</pre>\n";
|
return buffer + "</pre>\n";
|
||||||
},"19":function(container,depth0,helpers,partials,data) {
|
},"32":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return ((stack1 = container.lambda(depth0, depth0)) != null ? stack1 : "");
|
return ((stack1 = container.lambda(depth0, depth0)) != null ? stack1 : "");
|
||||||
},"21":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
},"34":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(22, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "");
|
return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(35, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "");
|
||||||
},"22":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
},"35":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(23, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(36, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ ((stack1 = container.invokePartial(partials.kanji,depth0,{"name":"kanji","hash":{"root":(depths[1] != null ? depths[1].root : depths[1]),"source":(depths[1] != null ? depths[1].source : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1]),"debug":(depths[1] != null ? depths[1].debug : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
|
+ ((stack1 = container.invokePartial(partials.kanji,depth0,{"name":"kanji","hash":{"root":(depths[1] != null ? depths[1].root : depths[1]),"source":(depths[1] != null ? depths[1].source : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1]),"debug":(depths[1] != null ? depths[1].debug : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
|
||||||
},"23":function(container,depth0,helpers,partials,data) {
|
},"36":function(container,depth0,helpers,partials,data) {
|
||||||
return "<hr>";
|
return "<hr>";
|
||||||
},"25":function(container,depth0,helpers,partials,data) {
|
},"38":function(container,depth0,helpers,partials,data) {
|
||||||
return "<p class=\"note\">No results found.</p>\n";
|
return "<p class=\"note\">No results found</p>\n";
|
||||||
},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return "\n"
|
return "\n\n"
|
||||||
+ ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(21, data, 0, blockParams, depths),"inverse":container.program(25, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "");
|
+ ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(34, data, 0, blockParams, depths),"inverse":container.program(38, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "");
|
||||||
},"main_d": function(fn, props, container, depth0, data, blockParams, depths) {
|
},"main_d": function(fn, props, container, depth0, data, blockParams, depths) {
|
||||||
|
|
||||||
var decorators = container.decorators;
|
var decorators = container.decorators;
|
||||||
|
|
||||||
fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(1, data, 0, blockParams, depths),"inverse":container.noop,"args":["kanji"],"data":data}) || fn;
|
fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(1, data, 0, blockParams, depths),"inverse":container.noop,"args":["table"],"data":data}) || fn;
|
||||||
|
fn = decorators.inline(fn,props,container,{"name":"inline","hash":{},"fn":container.program(10, data, 0, blockParams, depths),"inverse":container.noop,"args":["kanji"],"data":data}) || fn;
|
||||||
return fn;
|
return fn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,10 +259,12 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia
|
|||||||
if (stack1 != null) { buffer += stack1; }
|
if (stack1 != null) { buffer += stack1; }
|
||||||
return buffer + "</div>\n\n"
|
return buffer + "</div>\n\n"
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.reasons : depth0),{"name":"if","hash":{},"fn":container.program(20, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.reasons : depth0),{"name":"if","hash":{},"fn":container.program(20, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
|
+ "\n"
|
||||||
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.frequencies : depth0),{"name":"if","hash":{},"fn":container.program(24, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ "\n <div class=\"glossary\">\n"
|
+ "\n <div class=\"glossary\">\n"
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(24, data, 0),"inverse":container.program(30, data, 0),"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.grouped : depth0),{"name":"if","hash":{},"fn":container.program(27, data, 0),"inverse":container.program(33, data, 0),"data":data})) != null ? stack1 : "")
|
||||||
+ " </div>\n\n"
|
+ " </div>\n\n"
|
||||||
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(32, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers["if"].call(alias1,(depth0 != null ? depth0.debug : depth0),{"name":"if","hash":{},"fn":container.program(35, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ "</div>\n";
|
+ "</div>\n";
|
||||||
},"13":function(container,depth0,helpers,partials,data) {
|
},"13":function(container,depth0,helpers,partials,data) {
|
||||||
return " <a href=\"#\" class=\"action-view-note pending disabled\"><img src=\"/mixed/img/view-note.png\" title=\"View added note (Alt + V)\" alt></a>\n <a href=\"#\" class=\"action-add-note pending disabled\" data-mode=\"term-kanji\"><img src=\"/mixed/img/add-term-kanji.png\" title=\"Add expression (Alt + E)\" alt></a>\n <a href=\"#\" class=\"action-add-note pending disabled\" data-mode=\"term-kana\"><img src=\"/mixed/img/add-term-kana.png\" title=\"Add reading (Alt + R)\" alt></a>\n";
|
return " <a href=\"#\" class=\"action-view-note pending disabled\"><img src=\"/mixed/img/view-note.png\" title=\"View added note (Alt + V)\" alt></a>\n <a href=\"#\" class=\"action-add-note pending disabled\" data-mode=\"term-kanji\"><img src=\"/mixed/img/add-term-kanji.png\" title=\"Add expression (Alt + E)\" alt></a>\n <a href=\"#\" class=\"action-add-note pending disabled\" data-mode=\"term-kana\"><img src=\"/mixed/img/add-term-kana.png\" title=\"Add reading (Alt + R)\" alt></a>\n";
|
||||||
@ -242,53 +300,67 @@ templates['terms.html'] = template({"1":function(container,depth0,helpers,partia
|
|||||||
},"24":function(container,depth0,helpers,partials,data) {
|
},"24":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(25, data, 0),"inverse":container.program(28, data, 0),"data":data})) != null ? stack1 : "");
|
return " <div>\n"
|
||||||
|
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.frequencies : depth0),{"name":"each","hash":{},"fn":container.program(25, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
|
+ " </div>\n";
|
||||||
},"25":function(container,depth0,helpers,partials,data) {
|
},"25":function(container,depth0,helpers,partials,data) {
|
||||||
|
var helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;
|
||||||
|
|
||||||
|
return " <span class=\"label label-default tag-frequency\">"
|
||||||
|
+ alias4(((helper = (helper = helpers.dictionary || (depth0 != null ? depth0.dictionary : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"dictionary","hash":{},"data":data}) : helper)))
|
||||||
|
+ ":"
|
||||||
|
+ alias4(((helper = (helper = helpers.frequency || (depth0 != null ? depth0.frequency : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"frequency","hash":{},"data":data}) : helper)))
|
||||||
|
+ "</span>\n";
|
||||||
|
},"27":function(container,depth0,helpers,partials,data) {
|
||||||
|
var stack1;
|
||||||
|
|
||||||
|
return ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["1"] : stack1),{"name":"if","hash":{},"fn":container.program(28, data, 0),"inverse":container.program(31, data, 0),"data":data})) != null ? stack1 : "");
|
||||||
|
},"28":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return " <ol>\n"
|
return " <ol>\n"
|
||||||
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(26, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
+ ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(29, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ " </ol>\n";
|
+ " </ol>\n";
|
||||||
},"26":function(container,depth0,helpers,partials,data) {
|
},"29":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return " <li>"
|
return " <li>"
|
||||||
+ ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "")
|
+ ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "")
|
||||||
+ "</li>\n";
|
+ "</li>\n";
|
||||||
},"28":function(container,depth0,helpers,partials,data) {
|
},"31":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return ((stack1 = container.invokePartial(partials.definition,((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["0"] : stack1),{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
|
return ((stack1 = container.invokePartial(partials.definition,((stack1 = (depth0 != null ? depth0.definitions : depth0)) != null ? stack1["0"] : stack1),{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
|
||||||
},"30":function(container,depth0,helpers,partials,data) {
|
},"33":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
|
return ((stack1 = container.invokePartial(partials.definition,depth0,{"name":"definition","data":data,"indent":" ","helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
|
||||||
},"32":function(container,depth0,helpers,partials,data) {
|
},"35":function(container,depth0,helpers,partials,data) {
|
||||||
var stack1, helper, options, buffer =
|
var stack1, helper, options, buffer =
|
||||||
" <pre>";
|
" <pre>";
|
||||||
stack1 = ((helper = (helper = helpers.dumpObject || (depth0 != null ? depth0.dumpObject : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"dumpObject","hash":{},"fn":container.program(18, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
|
stack1 = ((helper = (helper = helpers.dumpObject || (depth0 != null ? depth0.dumpObject : depth0)) != null ? helper : helpers.helperMissing),(options={"name":"dumpObject","hash":{},"fn":container.program(18, data, 0),"inverse":container.noop,"data":data}),(typeof helper === "function" ? helper.call(depth0 != null ? depth0 : (container.nullContext || {}),options) : helper));
|
||||||
if (!helpers.dumpObject) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
|
if (!helpers.dumpObject) { stack1 = helpers.blockHelperMissing.call(depth0,stack1,options)}
|
||||||
if (stack1 != null) { buffer += stack1; }
|
if (stack1 != null) { buffer += stack1; }
|
||||||
return buffer + "</pre>\n";
|
return buffer + "</pre>\n";
|
||||||
},"34":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
},"37":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(35, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "");
|
return ((stack1 = helpers.each.call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"each","hash":{},"fn":container.program(38, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "");
|
||||||
},"35":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
},"38":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(36, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
return ((stack1 = helpers.unless.call(depth0 != null ? depth0 : (container.nullContext || {}),(data && data.first),{"name":"unless","hash":{},"fn":container.program(39, data, 0, blockParams, depths),"inverse":container.noop,"data":data})) != null ? stack1 : "")
|
||||||
+ "\n"
|
+ "\n"
|
||||||
+ ((stack1 = container.invokePartial(partials.term,depth0,{"name":"term","hash":{"playback":(depths[1] != null ? depths[1].playback : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1]),"grouped":(depths[1] != null ? depths[1].grouped : depths[1]),"debug":(depths[1] != null ? depths[1].debug : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
|
+ ((stack1 = container.invokePartial(partials.term,depth0,{"name":"term","hash":{"playback":(depths[1] != null ? depths[1].playback : depths[1]),"addable":(depths[1] != null ? depths[1].addable : depths[1]),"grouped":(depths[1] != null ? depths[1].grouped : depths[1]),"debug":(depths[1] != null ? depths[1].debug : depths[1])},"data":data,"helpers":helpers,"partials":partials,"decorators":container.decorators})) != null ? stack1 : "");
|
||||||
},"36":function(container,depth0,helpers,partials,data) {
|
},"39":function(container,depth0,helpers,partials,data) {
|
||||||
return "<hr>";
|
return "<hr>";
|
||||||
},"38":function(container,depth0,helpers,partials,data) {
|
},"41":function(container,depth0,helpers,partials,data) {
|
||||||
return "<p class=\"note\">No results found.</p>\n";
|
return "<p class=\"note\">No results found.</p>\n";
|
||||||
},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data,blockParams,depths) {
|
||||||
var stack1;
|
var stack1;
|
||||||
|
|
||||||
return "\n\n"
|
return "\n\n"
|
||||||
+ ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(34, data, 0, blockParams, depths),"inverse":container.program(38, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "");
|
+ ((stack1 = helpers["if"].call(depth0 != null ? depth0 : (container.nullContext || {}),(depth0 != null ? depth0.definitions : depth0),{"name":"if","hash":{},"fn":container.program(37, data, 0, blockParams, depths),"inverse":container.program(41, data, 0, blockParams, depths),"data":data})) != null ? stack1 : "");
|
||||||
},"main_d": function(fn, props, container, depth0, data, blockParams, depths) {
|
},"main_d": function(fn, props, container, depth0, data, blockParams, depths) {
|
||||||
|
|
||||||
var decorators = container.decorators;
|
var decorators = container.decorators;
|
||||||
|
@ -37,8 +37,26 @@ class Translator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async findTermsGrouped(text, dictionaries, alphanumeric) {
|
async findTermsGrouped(text, dictionaries, alphanumeric) {
|
||||||
|
const titles = Object.keys(dictionaries);
|
||||||
const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric);
|
const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric);
|
||||||
return {length, definitions: dictTermsGroup(definitions, dictionaries)};
|
|
||||||
|
const definitionsGrouped = dictTermsGroup(definitions, dictionaries);
|
||||||
|
for (const definition of definitionsGrouped) {
|
||||||
|
await this.buildTermFrequencies(definition, titles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {length, definitions: definitionsGrouped};
|
||||||
|
}
|
||||||
|
|
||||||
|
async findTermsSplit(text, dictionaries, alphanumeric) {
|
||||||
|
const titles = Object.keys(dictionaries);
|
||||||
|
const {length, definitions} = await this.findTerms(text, dictionaries, alphanumeric);
|
||||||
|
|
||||||
|
for (const definition of definitions) {
|
||||||
|
await this.buildTermFrequencies(definition, titles);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {length, definitions};
|
||||||
}
|
}
|
||||||
|
|
||||||
async findTerms(text, dictionaries, alphanumeric) {
|
async findTerms(text, dictionaries, alphanumeric) {
|
||||||
@ -51,17 +69,18 @@ class Translator {
|
|||||||
|
|
||||||
const cache = {};
|
const cache = {};
|
||||||
const titles = Object.keys(dictionaries);
|
const titles = Object.keys(dictionaries);
|
||||||
let deinflections = await this.findTermsDeinflected(text, titles, cache);
|
let deinflections = await this.findTermDeinflections(text, titles, cache);
|
||||||
const textHiragana = jpKatakanaToHiragana(text);
|
const textHiragana = jpKatakanaToHiragana(text);
|
||||||
if (text !== textHiragana) {
|
if (text !== textHiragana) {
|
||||||
deinflections = deinflections.concat(await this.findTermsDeinflected(textHiragana, titles, cache));
|
deinflections = deinflections.concat(await this.findTermDeinflections(textHiragana, titles, cache));
|
||||||
}
|
}
|
||||||
|
|
||||||
let definitions = [];
|
let definitions = [];
|
||||||
for (const deinflection of deinflections) {
|
for (const deinflection of deinflections) {
|
||||||
for (const definition of deinflection.definitions) {
|
for (const definition of deinflection.definitions) {
|
||||||
const tags = definition.tags.map(tag => dictTagBuild(tag, definition.tagMeta));
|
const tags = await this.expandTags(definition.tags, definition.dictionary);
|
||||||
tags.push(dictTagBuildSource(definition.dictionary));
|
tags.push(dictTagBuildSource(definition.dictionary));
|
||||||
|
|
||||||
definitions.push({
|
definitions.push({
|
||||||
source: deinflection.source,
|
source: deinflection.source,
|
||||||
reasons: deinflection.reasons,
|
reasons: deinflection.reasons,
|
||||||
@ -87,7 +106,7 @@ class Translator {
|
|||||||
return {length, definitions};
|
return {length, definitions};
|
||||||
}
|
}
|
||||||
|
|
||||||
async findTermsDeinflected(text, titles, cache) {
|
async findTermDeinflections(text, titles, cache) {
|
||||||
const definer = async term => {
|
const definer = async term => {
|
||||||
if (cache.hasOwnProperty(term)) {
|
if (cache.hasOwnProperty(term)) {
|
||||||
return cache[term];
|
return cache[term];
|
||||||
@ -117,11 +136,88 @@ class Translator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const definition of definitions) {
|
for (const definition of definitions) {
|
||||||
const tags = definition.tags.map(tag => dictTagBuild(tag, definition.tagMeta));
|
const tags = await this.expandTags(definition.tags, definition.dictionary);
|
||||||
tags.push(dictTagBuildSource(definition.dictionary));
|
tags.push(dictTagBuildSource(definition.dictionary));
|
||||||
|
|
||||||
definition.tags = dictTagsSort(tags);
|
definition.tags = dictTagsSort(tags);
|
||||||
|
definition.stats = await this.expandStats(definition.stats, definition.dictionary);
|
||||||
|
|
||||||
|
definition.frequencies = [];
|
||||||
|
for (const meta of await this.database.findKanjiMeta(definition.character, titles)) {
|
||||||
|
if (meta.mode === 'freq') {
|
||||||
|
definition.frequencies.push({
|
||||||
|
character: meta.character,
|
||||||
|
frequency: meta.data,
|
||||||
|
dictionary: meta.dictionary
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return definitions;
|
return definitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async buildTermFrequencies(definition, titles) {
|
||||||
|
definition.frequencies = [];
|
||||||
|
for (const meta of await this.database.findTermMeta(definition.expression, titles)) {
|
||||||
|
if (meta.mode === 'freq') {
|
||||||
|
definition.frequencies.push({
|
||||||
|
expression: meta.expression,
|
||||||
|
frequency: meta.data,
|
||||||
|
dictionary: meta.dictionary
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async expandTags(names, title) {
|
||||||
|
const tags = [];
|
||||||
|
for (const name of names) {
|
||||||
|
const base = name.split(':')[0];
|
||||||
|
const meta = await this.database.findTagForTitle(base, title);
|
||||||
|
|
||||||
|
const tag = {name};
|
||||||
|
for (const prop in meta || {}) {
|
||||||
|
if (prop !== 'name') {
|
||||||
|
tag[prop] = meta[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tags.push(dictTagSanitize(tag));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
async expandStats(items, title) {
|
||||||
|
const stats = {};
|
||||||
|
for (const name in items) {
|
||||||
|
const base = name.split(':')[0];
|
||||||
|
const meta = await this.database.findTagForTitle(base, title);
|
||||||
|
const group = stats[meta.category] = stats[meta.category] || [];
|
||||||
|
|
||||||
|
const stat = {name, value: items[name]};
|
||||||
|
for (const prop in meta || {}) {
|
||||||
|
if (prop !== 'name') {
|
||||||
|
stat[prop] = meta[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
group.push(dictTagSanitize(stat));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const category in stats) {
|
||||||
|
stats[category].sort((a, b) => {
|
||||||
|
if (a.notes < b.notes) {
|
||||||
|
return -1;
|
||||||
|
} else if (a.notes > b.notes) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,8 +42,8 @@ function utilAnkiGetModelFieldNames(modelName) {
|
|||||||
return utilBackend().anki.getModelFieldNames(modelName);
|
return utilBackend().anki.getModelFieldNames(modelName);
|
||||||
}
|
}
|
||||||
|
|
||||||
function utilDatabaseGetDictionaries() {
|
function utilDatabaseGetTitles() {
|
||||||
return utilBackend().translator.database.getDictionaries();
|
return utilBackend().translator.database.getTitles();
|
||||||
}
|
}
|
||||||
|
|
||||||
function utilDatabasePurge() {
|
function utilDatabasePurge() {
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<link rel="stylesheet" type="text/css" href="/mixed/lib/bootstrap/css/bootstrap-theme.min.css">
|
<link rel="stylesheet" type="text/css" href="/mixed/lib/bootstrap/css/bootstrap-theme.min.css">
|
||||||
<style>
|
<style>
|
||||||
#anki-spinner, #anki-general, #anki-error,
|
#anki-spinner, #anki-general, #anki-error,
|
||||||
#dict-spinner, #dict-error, #dict-warning, #dict-purge-progress, #dict-import-progress,
|
#dict-spinner, #dict-error, #dict-warning, #dict-purge, #dict-import-progress,
|
||||||
#debug, .options-advanced {
|
#debug, .options-advanced {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -96,6 +96,10 @@
|
|||||||
<label><input type="checkbox" id="search-alphanumeric"> Search alphanumeric text</label>
|
<label><input type="checkbox" id="search-alphanumeric"> Search alphanumeric text</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="checkbox">
|
||||||
|
<label><input type="checkbox" id="auto-hide-results"> Automatically hide results</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="form-group options-advanced">
|
<div class="form-group options-advanced">
|
||||||
<label for="scan-delay">Scan delay (in milliseconds)</label>
|
<label for="scan-delay">Scan delay (in milliseconds)</label>
|
||||||
<input type="number" min="1" id="scan-delay" class="form-control">
|
<input type="number" min="1" id="scan-delay" class="form-control">
|
||||||
@ -125,24 +129,16 @@
|
|||||||
|
|
||||||
<p class="help-block">
|
<p class="help-block">
|
||||||
Yomichan can import and use a variety of dictionary formats. Unneeded dictionaries can be disabled,
|
Yomichan can import and use a variety of dictionary formats. Unneeded dictionaries can be disabled,
|
||||||
or you can simply <a href="#" id="dict-purge">purge the database</a> to delete everything.
|
or you can simply <a href="#" id="dict-purge-link">purge the database</a> to delete everything.
|
||||||
</p>
|
</p>
|
||||||
<p class="help-block">
|
<p class="help-block">
|
||||||
Please visit the <a href="https://foosoft.net/projects/yomichan" target="_blank">Yomichan</a> homepage to download free
|
Please visit the <a href="https://foosoft.net/projects/yomichan" target="_blank">Yomichan</a> homepage to download free
|
||||||
dictionaries that you can use with this extension.
|
dictionaries that you can use with this extension.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div id="dict-purge-progress" class="text-danger">Dictionary data is being purged, please be patient...</div>
|
<div class="text-danger" id="dict-purge">Dictionary data is being purged, please be patient...</div>
|
||||||
|
<div class="alert alert-warning" id="dict-warning">No dictionaries have been installed</div>
|
||||||
<div class="alert alert-warning" id="dict-warning">
|
<div class="alert alert-danger" id="dict-error"></div>
|
||||||
<strong>Warning:</strong>
|
|
||||||
<span>no dictionaries found; please use the importer below to install packaged dictionaries</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="alert alert-danger" id="dict-error">
|
|
||||||
<strong>Error:</strong>
|
|
||||||
<span></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="dict-groups"></div>
|
<div id="dict-groups"></div>
|
||||||
|
|
||||||
@ -170,10 +166,7 @@
|
|||||||
<a href="https://foosoft.net/projects/anki-connect/" target="_blank">AnkiConnect</a> plugin.
|
<a href="https://foosoft.net/projects/anki-connect/" target="_blank">AnkiConnect</a> plugin.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="alert alert-danger" id="anki-error">
|
<div class="alert alert-danger" id="anki-error"></div>
|
||||||
<strong>Error:</strong>
|
|
||||||
<span></span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<label><input type="checkbox" id="anki-enable"> Enable Anki integration</label>
|
<label><input type="checkbox" id="anki-enable"> Enable Anki integration</label>
|
||||||
|
@ -86,7 +86,7 @@ function docRangeFromPoint(point) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const range = document.caretRangeFromPoint(point.x, point.y);
|
const range = document.caretRangeFromPoint(point.x, point.y);
|
||||||
if (range) {
|
if (range && range.startContainer.nodeType === 3 && range.endContainer.nodeType === 3) {
|
||||||
return new TextSourceRange(range);
|
return new TextSourceRange(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ class DisplayFloat extends Display {
|
|||||||
if (window.yomichan_orphaned) {
|
if (window.yomichan_orphaned) {
|
||||||
this.onOrphaned();
|
this.onOrphaned();
|
||||||
} else {
|
} else {
|
||||||
window.alert(`Error: ${error}`);
|
window.alert(`Error: ${error.toString ? error.toString() : error}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +80,6 @@ class Frontend {
|
|||||||
const search = async () => {
|
const search = async () => {
|
||||||
try {
|
try {
|
||||||
await this.searchAt({x: e.clientX, y: e.clientY});
|
await this.searchAt({x: e.clientX, y: e.clientY});
|
||||||
this.pendingLookup = false;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.onError(e);
|
this.onError(e);
|
||||||
}
|
}
|
||||||
@ -153,7 +152,7 @@ class Frontend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onError(error) {
|
onError(error) {
|
||||||
window.alert(`Error: ${error}`);
|
window.alert(`Error: ${error.toString ? error.toString() : error}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
popupTimerSet(callback) {
|
popupTimerSet(callback) {
|
||||||
@ -169,27 +168,17 @@ class Frontend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async searchAt(point) {
|
async searchAt(point) {
|
||||||
let textSource = null;
|
if (this.pendingLookup || this.popup.containsPoint(point)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const textSource = docRangeFromPoint(point);
|
||||||
|
let hideResults = !textSource || !textSource.containsPoint(point);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.pendingLookup) {
|
if (!hideResults && (!this.textSourceLast || !this.textSourceLast.equals(textSource))) {
|
||||||
return;
|
this.pendingLookup = true;
|
||||||
}
|
hideResults = !await this.searchTerms(textSource) && !await this.searchKanji(textSource);
|
||||||
|
|
||||||
textSource = docRangeFromPoint(point);
|
|
||||||
if (!textSource || !textSource.containsPoint(point)) {
|
|
||||||
docImposterDestroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.textSourceLast && this.textSourceLast.equals(textSource)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.pendingLookup = true;
|
|
||||||
|
|
||||||
if (!await this.searchTerms(textSource)) {
|
|
||||||
await this.searchKanji(textSource);
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (window.yomichan_orphaned) {
|
if (window.yomichan_orphaned) {
|
||||||
@ -200,7 +189,12 @@ class Frontend {
|
|||||||
this.onError(e);
|
this.onError(e);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
docImposterDestroy();
|
if (hideResults && this.options.scanning.autoHideResults) {
|
||||||
|
this.searchClear();
|
||||||
|
} else {
|
||||||
|
docImposterDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
this.pendingLookup = false;
|
this.pendingLookup = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,6 +100,21 @@ class Popup {
|
|||||||
return this.injected && this.container.style.visibility !== 'hidden';
|
return this.injected && this.container.style.visibility !== 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
containsPoint(point) {
|
||||||
|
if (!this.isVisible()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rect = this.container.getBoundingClientRect();
|
||||||
|
const contained =
|
||||||
|
point.x >= rect.left &&
|
||||||
|
point.y >= rect.top &&
|
||||||
|
point.x < rect.right &&
|
||||||
|
point.y < rect.bottom;
|
||||||
|
|
||||||
|
return contained;
|
||||||
|
}
|
||||||
|
|
||||||
async termsShow(elementRect, definitions, options, context) {
|
async termsShow(elementRect, definitions, options, context) {
|
||||||
await this.show(elementRect, options);
|
await this.show(elementRect, options);
|
||||||
this.invokeApi('termsShow', {definitions, options, context});
|
this.invokeApi('termsShow', {definitions, options, context});
|
||||||
|
@ -82,7 +82,7 @@ class TextSourceRange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
equals(other) {
|
equals(other) {
|
||||||
return other.range && other.range.compareBoundaryPoints(Range.START_TO_START, this.range) === 0;
|
return other && other.range && other.range.compareBoundaryPoints(Range.START_TO_START, this.range) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static shouldEnter(node) {
|
static shouldEnter(node) {
|
||||||
@ -239,6 +239,6 @@ class TextSourceElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
equals(other) {
|
equals(other) {
|
||||||
return other.element === this.element && other.content === this.content;
|
return other && other.element === this.element && other.content === this.content;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"name": "Yomichan",
|
"name": "Yomichan",
|
||||||
"version": "1.3.5",
|
"version": "1.4.0",
|
||||||
|
|
||||||
"description": "Japanese dictionary with Anki integration",
|
"description": "Japanese dictionary with Anki integration",
|
||||||
"icons": {"16": "mixed/img/icon16.png", "48": "mixed/img/icon48.png", "128": "mixed/img/icon128.png"},
|
"icons": {"16": "mixed/img/icon16.png", "48": "mixed/img/icon48.png", "128": "mixed/img/icon128.png"},
|
||||||
|
@ -84,6 +84,10 @@ hr {
|
|||||||
background-color: #aa66cc;
|
background-color: #aa66cc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag-frequency {
|
||||||
|
background-color: #5cb85c;
|
||||||
|
}
|
||||||
|
|
||||||
.actions .disabled {
|
.actions .disabled {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
@ -144,3 +148,15 @@ hr {
|
|||||||
padding: 0.01em;
|
padding: 0.01em;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.glyph-data {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-output {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-output td {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
@ -32,11 +32,11 @@ class Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onError(error) {
|
onError(error) {
|
||||||
throw 'override me';
|
throw 'Override me';
|
||||||
}
|
}
|
||||||
|
|
||||||
onSearchClear() {
|
onSearchClear() {
|
||||||
throw 'override me';
|
throw 'Override me';
|
||||||
}
|
}
|
||||||
|
|
||||||
onSourceTermView(e) {
|
onSourceTermView(e) {
|
||||||
@ -350,7 +350,7 @@ class Display {
|
|||||||
Display.adderButtonFind(index, mode).addClass('disabled');
|
Display.adderButtonFind(index, mode).addClass('disabled');
|
||||||
Display.viewerButtonFind(index).removeClass('pending disabled').data('noteId', noteId);
|
Display.viewerButtonFind(index).removeClass('pending disabled').data('noteId', noteId);
|
||||||
} else {
|
} else {
|
||||||
throw 'note could note be added';
|
throw 'Note could note be added';
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.onError(e);
|
this.onError(e);
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
{{#*inline "table"}}
|
||||||
|
{{#if data}}
|
||||||
|
<table class="info-output">
|
||||||
|
{{#each data}}
|
||||||
|
<tr>
|
||||||
|
<th>{{#if notes}}{{notes}}{{else}}{{name}}{{/if}}</th>
|
||||||
|
<td>{{value}}</td>
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</table>
|
||||||
|
{{else}}
|
||||||
|
No data found
|
||||||
|
{{/if}}
|
||||||
|
{{/inline}}
|
||||||
|
|
||||||
{{#*inline "kanji"}}
|
{{#*inline "kanji"}}
|
||||||
<div class="entry" data-type="kanji">
|
<div class="entry" data-type="kanji">
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
@ -13,44 +28,61 @@
|
|||||||
|
|
||||||
<div class="glyph">{{character}}</div>
|
<div class="glyph">{{character}}</div>
|
||||||
|
|
||||||
<div class="reading">
|
{{#if frequencies}}
|
||||||
<table>
|
<div>
|
||||||
<tr>
|
{{#each frequencies}}
|
||||||
<th>Kunyomi:</th>
|
<span class="label label-default tag-frequency">{{dictionary}}:{{frequency}}</span>
|
||||||
<td>
|
{{/each}}
|
||||||
{{#each kunyomi}}
|
|
||||||
{{.}}{{#unless @last}}, {{/unless}}
|
|
||||||
{{/each}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<th>Onyomi:</th>
|
|
||||||
<td>
|
|
||||||
{{#each onyomi}}
|
|
||||||
{{.}}{{#unless @last}}, {{/unless}}
|
|
||||||
{{/each}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if tags}}
|
||||||
<div>
|
<div>
|
||||||
{{#each tags}}
|
{{#each tags}}
|
||||||
<span class="label label-default tag-{{category}}" title="{{notes}}">{{name}}</span>
|
<span class="label label-default tag-{{category}}" title="{{notes}}">{{name}}</span>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="glossary">
|
<table class="table table-condensed glyph-data">
|
||||||
{{#if glossary.[1]}}
|
<tr>
|
||||||
<ol>
|
<th>Glossary</th>
|
||||||
{{#each glossary}}
|
<th>Readings</th>
|
||||||
<li><span class="glossary-item">{{#multiLine}}{{.}}{{/multiLine}}</span></li>
|
<th>Statistics</th>
|
||||||
{{/each}}
|
</tr>
|
||||||
</ol>
|
<tr>
|
||||||
{{else}}
|
<td class="glossary">
|
||||||
<div class="glossary-item">{{#multiLine}}{{glossary.[0]}}{{/multiLine}}</div>
|
{{#if glossary.[1]}}
|
||||||
{{/if}}
|
<ol>{{#each glossary}}<li><span class="glossary-item">{{.}}</span></li>{{/each}}</ol>
|
||||||
</div>
|
{{else}}
|
||||||
|
<span class="glossary-item">{{glossary.[0]}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</td>
|
||||||
|
<td class="reading">
|
||||||
|
{{#if onyomi}}<dl>{{#each onyomi}}<dd>{{.}}</dd>{{/each}}</dl>{{/if}}
|
||||||
|
{{#if kunyomi}}<dl>{{#each kunyomi}}<dd>{{.}}</dd>{{/each}}</dl>{{/if}}
|
||||||
|
</td>
|
||||||
|
<td>{{> table data=stats.misc}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th colspan="3">Classifications</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">{{> table data=stats.class}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th colspan="3">Codepoints</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">{{> table data=stats.code}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th colspan="3">Dictionary Indices</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">{{> table data=stats.index}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
{{#if debug}}
|
{{#if debug}}
|
||||||
<pre>{{#dumpObject}}{{{.}}}{{/dumpObject}}</pre>
|
<pre>{{#dumpObject}}{{{.}}}{{/dumpObject}}</pre>
|
||||||
@ -64,5 +96,5 @@
|
|||||||
{{> kanji debug=../debug addable=../addable source=../source root=../root}}
|
{{> kanji debug=../debug addable=../addable source=../source root=../root}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<p class="note">No results found.</p>
|
<p class="note">No results found</p>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -41,6 +41,14 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if frequencies}}
|
||||||
|
<div>
|
||||||
|
{{#each frequencies}}
|
||||||
|
<span class="label label-default tag-frequency">{{dictionary}}:{{frequency}}</span>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
<div class="glossary">
|
<div class="glossary">
|
||||||
{{#if grouped}}
|
{{#if grouped}}
|
||||||
{{#if definitions.[1]}}
|
{{#if definitions.[1]}}
|
||||||
|
Loading…
Reference in New Issue
Block a user