From ced7bf5f27c72b98fae3b2d24f1820e0083c22bf Mon Sep 17 00:00:00 2001 From: Alex Yatskov Date: Sat, 26 Mar 2016 14:21:51 -0700 Subject: File reorg --- ext/background.html | 8 +-- ext/bg/deinflector.js | 126 +++++++++++++++++++++++++++++++++++++++++ ext/bg/dictionary.js | 84 ++++++++++++++++++++++++++++ ext/bg/translator.js | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++ ext/bg/yomichan.js | 73 ++++++++++++++++++++++++ ext/jp/deinflector.js | 126 ----------------------------------------- ext/jp/dictionary.js | 84 ---------------------------- ext/jp/translator.js | 151 -------------------------------------------------- ext/jp/yomichan.js | 73 ------------------------ 9 files changed, 438 insertions(+), 438 deletions(-) create mode 100644 ext/bg/deinflector.js create mode 100644 ext/bg/dictionary.js create mode 100644 ext/bg/translator.js create mode 100644 ext/bg/yomichan.js delete mode 100644 ext/jp/deinflector.js delete mode 100644 ext/jp/dictionary.js delete mode 100644 ext/jp/translator.js delete mode 100644 ext/jp/yomichan.js (limited to 'ext') diff --git a/ext/background.html b/ext/background.html index 665bc968..6bf22bf0 100644 --- a/ext/background.html +++ b/ext/background.html @@ -2,9 +2,9 @@ - - - - + + + + diff --git a/ext/bg/deinflector.js b/ext/bg/deinflector.js new file mode 100644 index 00000000..03f9d40a --- /dev/null +++ b/ext/bg/deinflector.js @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2016 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +class Deinflection { + constructor(term, tags=[], rule='') { + this.children = []; + this.term = term; + this.tags = tags; + this.rule = rule; + } + + validate(validator) { + for (const tags of validator(this.term)) { + if (this.tags.length === 0) { + return true; + } + + for (const tag of this.tags) { + if (this.searchTags(tag, tags)) { + return true; + } + } + } + + return false; + } + + deinflect(validator, rules) { + if (this.validate(validator)) { + const child = new Deinflection(this.term); + this.children.push(child); + } + + for (const rule in rules) { + const variants = rules[rule]; + for (const v of variants) { + let allowed = this.tags.length === 0; + for (const tag of this.tags) { + if (this.searchTags(tag, v.tagsIn)) { + allowed = true; + break; + } + } + + if (!allowed || !this.term.endsWith(v.kanaIn)) { + continue; + } + + const term = this.term.slice(0, -v.kanaIn.length) + v.kanaOut; + const child = new Deinflection(term, v.tagsOut, rule); + if (child.deinflect(validator, rules)) { + this.children.push(child); + } + } + } + + return this.children.length > 0; + } + + searchTags(tag, tags) { + for (const t of tags) { + const re = new RegExp(tag); + if (re.test(t)) { + return true; + } + } + + return false; + } + + gather() { + if (this.children.length === 0) { + return [{root: this.term, rules: []}]; + } + + const paths = []; + for (const child of this.children) { + for (const path of child.gather()) { + if (this.rule.length > 0) { + path.rules.push(this.rule); + } + + path.source = this.term; + paths.push(path); + } + } + + return paths; + } +} + + +class Deinflector { + constructor() { + this.rules = {}; + } + + setRules(rules) { + this.rules = rules; + } + + deinflect(term, validator) { + const node = new Deinflection(term); + if (node.deinflect(validator, this.rules)) { + return node.gather(); + } + + return null; + } +} diff --git a/ext/bg/dictionary.js b/ext/bg/dictionary.js new file mode 100644 index 00000000..eff54890 --- /dev/null +++ b/ext/bg/dictionary.js @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2016 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +class Dictionary { + constructor() { + this.termDicts = []; + this.kanjiDicts = []; + } + + addTermDict(termDict) { + this.termDicts.push(termDict); + } + + addKanjiDict(kanjiDict) { + this.kanjiDicts.push(kanjiDict); + } + + + findTerm(term) { + let results = []; + for (let dict of this.termDicts) { + results = results.concat(this.findTermInDict(term, dict)); + } + + return results; + } + + findKanji(kanji) { + const results = []; + for (let dict of this.kanjiDicts) { + const result = this.findKanjiInDict(kanji, dict); + if (result !== null) { + results.push(result); + } + } + + return results; + } + + findTermInDict(term, dict) { + return (dict.indices[term] || []).map(index => { + const [e, r, g, t] = dict.defs[index]; + return { + id: index, + expression: e, + reading: r, + glossary: g, + tags: t.split(' ') + }; + }); + } + + findKanjiInDict(kanji, dict) { + const def = dict.defs[kanji]; + if (def === null) { + return null; + } + + const [c, k, o, g] = def; + return { + id: kanji.charCodeAt(0), + character: c, + kunyomi: k, + onyomi: o, + glossary: g + }; + } +} diff --git a/ext/bg/translator.js b/ext/bg/translator.js new file mode 100644 index 00000000..7a610377 --- /dev/null +++ b/ext/bg/translator.js @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2016 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +class Translator { + constructor() { + this.dictionary = new Dictionary(); + this.deinflector = new Deinflector(); + this.initialized = false; + } + + loadData(paths, callback) { + if (this.initialized) { + callback(); + return; + } + + const loaders = []; + for (const key of ['rules', 'edict', 'enamdict', 'kanjidic']) { + loaders.push( + $.getJSON(chrome.extension.getURL(paths[key])) + ); + } + + $.when.apply($, loaders).done((rules, edict, enamdict, kanjidic) => { + this.deinflector.setRules(rules[0]); + + this.dictionary.addTermDict(edict[0]); + this.dictionary.addTermDict(enamdict[0]); + this.dictionary.addKanjiDict(kanjidic[0]); + + this.initialized = true; + + if (callback) { + callback(); + } + }); + } + + findTerm(text) { + const groups = {}; + for (let i = text.length; i > 0; --i) { + const term = text.slice(0, i); + + const dfs = this.deinflector.deinflect(term, t => { + const tags = []; + for (const d of this.dictionary.findTerm(t)) { + tags.push(d.tags); + } + + return tags; + }); + + if (dfs === null) { + this.processTerm(groups, term); + } else { + for (const df of dfs) { + this.processTerm(groups, df.source, df.rules, df.root); + } + } + } + + let results = []; + for (const key in groups) { + results.push(groups[key]); + } + + results = results.sort(this.resultSorter); + + let length = 0; + for (const result of results) { + length = Math.max(length, result.source.length); + } + + return {results: results, length: length}; + } + + findKanji(text) { + let results = []; + + const processed = {}; + for (const c of text) { + if (!processed.has(c)) { + results = results.concat(this.dictionary.findKanji(c)); + processed[c] = true; + } + } + + return results; + } + + processTerm(groups, source, rules=[], root='') { + for (const entry of this.dictionary.findTerm(root || source)) { + if (entry.id in groups) { + continue; + } + + groups[entry.id] = { + expression: entry.expression, + reading: entry.reading, + glossary: entry.glossary, + tags: entry.tags, + source: source, + rules: rules + }; + } + } + + resultSorter(v1, v2) { + const sl1 = v1.source.length; + const sl2 = v2.source.length; + if (sl1 > sl2) { + return -1; + } else if (sl1 < sl2) { + return 1; + } + + const p1 = v1.tags.indexOf('P') >= 0; + const p2 = v2.tags.indexOf('P') >= 0; + if (p1 && !p2) { + return -1; + } else if (!p1 && p2) { + return 1; + } + + const rl1 = v1.rules.length; + const rl2 = v2.rules.length; + if (rl1 < rl2) { + return -1; + } else if (rl2 > rl1) { + return 1; + } + + return 0; + } +} diff --git a/ext/bg/yomichan.js b/ext/bg/yomichan.js new file mode 100644 index 00000000..196785e1 --- /dev/null +++ b/ext/bg/yomichan.js @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2016 Alex Yatskov + * Author: Alex Yatskov + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +class Yomichan { + constructor() { + this.translator = new Translator(); + this.res = { + rules: 'bg/data/rules.json', + edict: 'bg/data/edict.json', + enamdict: 'bg/data/enamdict.json', + kanjidic: 'bg/data/kanjidic.json' + }; + + this.updateState('disabled'); + + chrome.runtime.onMessage.addListener(this.onMessage.bind(this)); + chrome.browserAction.onClicked.addListener(this.onBrowserAction.bind(this)); + } + + onFindTerm({term}) { + return this.translator.findTerm(term); + } + + onMessage(request, sender, callback) { + const {action, data} = request; + const handler = { + findTerm: this.onFindTerm + }[action]; + + if (handler !== null) { + const result = handler.call(this, data); + if (callback !== null) { + callback(result); + } + } + } + + onBrowserAction(tab) { + switch (this.state) { + case 'disabled': + this.updateState('loading'); + this.translator.loadData(this.res, () => this.updateState('enabled')); + break; + case 'enabled': + this.updateState('disabled'); + break; + } + } + + updateState(state) { + const text = {'disabled': '', 'enabled': 'on', 'loading': '...'}[state]; + chrome.browserAction.setBadgeText({text: text}); + this.state = state; + } +} + +window.yomichan = new Yomichan(); diff --git a/ext/jp/deinflector.js b/ext/jp/deinflector.js deleted file mode 100644 index 03f9d40a..00000000 --- a/ext/jp/deinflector.js +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -class Deinflection { - constructor(term, tags=[], rule='') { - this.children = []; - this.term = term; - this.tags = tags; - this.rule = rule; - } - - validate(validator) { - for (const tags of validator(this.term)) { - if (this.tags.length === 0) { - return true; - } - - for (const tag of this.tags) { - if (this.searchTags(tag, tags)) { - return true; - } - } - } - - return false; - } - - deinflect(validator, rules) { - if (this.validate(validator)) { - const child = new Deinflection(this.term); - this.children.push(child); - } - - for (const rule in rules) { - const variants = rules[rule]; - for (const v of variants) { - let allowed = this.tags.length === 0; - for (const tag of this.tags) { - if (this.searchTags(tag, v.tagsIn)) { - allowed = true; - break; - } - } - - if (!allowed || !this.term.endsWith(v.kanaIn)) { - continue; - } - - const term = this.term.slice(0, -v.kanaIn.length) + v.kanaOut; - const child = new Deinflection(term, v.tagsOut, rule); - if (child.deinflect(validator, rules)) { - this.children.push(child); - } - } - } - - return this.children.length > 0; - } - - searchTags(tag, tags) { - for (const t of tags) { - const re = new RegExp(tag); - if (re.test(t)) { - return true; - } - } - - return false; - } - - gather() { - if (this.children.length === 0) { - return [{root: this.term, rules: []}]; - } - - const paths = []; - for (const child of this.children) { - for (const path of child.gather()) { - if (this.rule.length > 0) { - path.rules.push(this.rule); - } - - path.source = this.term; - paths.push(path); - } - } - - return paths; - } -} - - -class Deinflector { - constructor() { - this.rules = {}; - } - - setRules(rules) { - this.rules = rules; - } - - deinflect(term, validator) { - const node = new Deinflection(term); - if (node.deinflect(validator, this.rules)) { - return node.gather(); - } - - return null; - } -} diff --git a/ext/jp/dictionary.js b/ext/jp/dictionary.js deleted file mode 100644 index eff54890..00000000 --- a/ext/jp/dictionary.js +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -class Dictionary { - constructor() { - this.termDicts = []; - this.kanjiDicts = []; - } - - addTermDict(termDict) { - this.termDicts.push(termDict); - } - - addKanjiDict(kanjiDict) { - this.kanjiDicts.push(kanjiDict); - } - - - findTerm(term) { - let results = []; - for (let dict of this.termDicts) { - results = results.concat(this.findTermInDict(term, dict)); - } - - return results; - } - - findKanji(kanji) { - const results = []; - for (let dict of this.kanjiDicts) { - const result = this.findKanjiInDict(kanji, dict); - if (result !== null) { - results.push(result); - } - } - - return results; - } - - findTermInDict(term, dict) { - return (dict.indices[term] || []).map(index => { - const [e, r, g, t] = dict.defs[index]; - return { - id: index, - expression: e, - reading: r, - glossary: g, - tags: t.split(' ') - }; - }); - } - - findKanjiInDict(kanji, dict) { - const def = dict.defs[kanji]; - if (def === null) { - return null; - } - - const [c, k, o, g] = def; - return { - id: kanji.charCodeAt(0), - character: c, - kunyomi: k, - onyomi: o, - glossary: g - }; - } -} diff --git a/ext/jp/translator.js b/ext/jp/translator.js deleted file mode 100644 index 7a610377..00000000 --- a/ext/jp/translator.js +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -class Translator { - constructor() { - this.dictionary = new Dictionary(); - this.deinflector = new Deinflector(); - this.initialized = false; - } - - loadData(paths, callback) { - if (this.initialized) { - callback(); - return; - } - - const loaders = []; - for (const key of ['rules', 'edict', 'enamdict', 'kanjidic']) { - loaders.push( - $.getJSON(chrome.extension.getURL(paths[key])) - ); - } - - $.when.apply($, loaders).done((rules, edict, enamdict, kanjidic) => { - this.deinflector.setRules(rules[0]); - - this.dictionary.addTermDict(edict[0]); - this.dictionary.addTermDict(enamdict[0]); - this.dictionary.addKanjiDict(kanjidic[0]); - - this.initialized = true; - - if (callback) { - callback(); - } - }); - } - - findTerm(text) { - const groups = {}; - for (let i = text.length; i > 0; --i) { - const term = text.slice(0, i); - - const dfs = this.deinflector.deinflect(term, t => { - const tags = []; - for (const d of this.dictionary.findTerm(t)) { - tags.push(d.tags); - } - - return tags; - }); - - if (dfs === null) { - this.processTerm(groups, term); - } else { - for (const df of dfs) { - this.processTerm(groups, df.source, df.rules, df.root); - } - } - } - - let results = []; - for (const key in groups) { - results.push(groups[key]); - } - - results = results.sort(this.resultSorter); - - let length = 0; - for (const result of results) { - length = Math.max(length, result.source.length); - } - - return {results: results, length: length}; - } - - findKanji(text) { - let results = []; - - const processed = {}; - for (const c of text) { - if (!processed.has(c)) { - results = results.concat(this.dictionary.findKanji(c)); - processed[c] = true; - } - } - - return results; - } - - processTerm(groups, source, rules=[], root='') { - for (const entry of this.dictionary.findTerm(root || source)) { - if (entry.id in groups) { - continue; - } - - groups[entry.id] = { - expression: entry.expression, - reading: entry.reading, - glossary: entry.glossary, - tags: entry.tags, - source: source, - rules: rules - }; - } - } - - resultSorter(v1, v2) { - const sl1 = v1.source.length; - const sl2 = v2.source.length; - if (sl1 > sl2) { - return -1; - } else if (sl1 < sl2) { - return 1; - } - - const p1 = v1.tags.indexOf('P') >= 0; - const p2 = v2.tags.indexOf('P') >= 0; - if (p1 && !p2) { - return -1; - } else if (!p1 && p2) { - return 1; - } - - const rl1 = v1.rules.length; - const rl2 = v2.rules.length; - if (rl1 < rl2) { - return -1; - } else if (rl2 > rl1) { - return 1; - } - - return 0; - } -} diff --git a/ext/jp/yomichan.js b/ext/jp/yomichan.js deleted file mode 100644 index 5c2b579f..00000000 --- a/ext/jp/yomichan.js +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2016 Alex Yatskov - * Author: Alex Yatskov - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -class Yomichan { - constructor() { - this.translator = new Translator(); - this.res = { - rules: 'jp/data/rules.json', - edict: 'jp/data/edict.json', - enamdict: 'jp/data/enamdict.json', - kanjidic: 'jp/data/kanjidic.json' - }; - - this.updateState('disabled'); - - chrome.runtime.onMessage.addListener(this.onMessage.bind(this)); - chrome.browserAction.onClicked.addListener(this.onBrowserAction.bind(this)); - } - - onFindTerm({term}) { - return this.translator.findTerm(term); - } - - onMessage(request, sender, callback) { - const {action, data} = request; - const handler = { - findTerm: this.onFindTerm - }[action]; - - if (handler !== null) { - const result = handler.call(this, data); - if (callback !== null) { - callback(result); - } - } - } - - onBrowserAction(tab) { - switch (this.state) { - case 'disabled': - this.updateState('loading'); - this.translator.loadData(this.res, () => this.updateState('enabled')); - break; - case 'enabled': - this.updateState('disabled'); - break; - } - } - - updateState(state) { - const text = {'disabled': '', 'enabled': 'on', 'loading': '...'}[state]; - chrome.browserAction.setBadgeText({text: text}); - this.state = state; - } -} - -window.yomichan = new Yomichan(); -- cgit v1.2.3