add chrome support; fix two text grabbing problems; eliminate unused lookup queue concept
This commit is contained in:
1 parent
4e023274ce
commit
56ce705a53
16 files changed
+1635
-169
No files matched your search
@@ -0,0 +1 @@
|
||||
dict/JMDict*.json
|
||||
+82
-52
@@ -2,6 +2,15 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
if (navigator.userAgent.indexOf('Chrome') > -1)
|
||||
{
|
||||
var ischrome = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var ischrome = false;
|
||||
}
|
||||
|
||||
// updated by a timer looping function, based on local storage set by the options page
|
||||
// we only use a tiny number of settings here
|
||||
|
||||
@@ -55,16 +64,19 @@ let lookup_epwing_kana = new Map();
|
||||
async function refresh_epwing()
|
||||
{
|
||||
let myjson = (await browser.storage.local.get("epwing"))["epwing"];
|
||||
epwing = JSON.parse(myjson);
|
||||
lookup_epwing_kan = new Map();
|
||||
lookup_epwing_kana = new Map();
|
||||
for (let i = 1; i < epwing.length; i++)
|
||||
if(myjson !== undefined)
|
||||
{
|
||||
if(typeof epwing[i] === 'string' || epwing[i] instanceof String)
|
||||
continue;
|
||||
add_epwing_id(epwing[i]["r"], i);
|
||||
for(let spelling of epwing[i]["s"])
|
||||
add_epwing_id(spelling, i);
|
||||
epwing = JSON.parse(myjson);
|
||||
lookup_epwing_kan = new Map();
|
||||
lookup_epwing_kana = new Map();
|
||||
for (let i = 1; i < epwing.length; i++)
|
||||
{
|
||||
if(typeof epwing[i] === 'string' || epwing[i] instanceof String)
|
||||
continue;
|
||||
add_epwing_id(epwing[i]["r"], i);
|
||||
for(let spelling of epwing[i]["s"])
|
||||
add_epwing_id(spelling, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
refresh_epwing();
|
||||
@@ -359,6 +371,7 @@ function load_deconjugation_rules(filename)
|
||||
{
|
||||
if (req.readyState === 4)
|
||||
{
|
||||
console.log("loaded deconjugation rules");
|
||||
if (req.status === 200)
|
||||
rules = JSON.parse(req.responseText);
|
||||
else
|
||||
@@ -532,12 +545,11 @@ tetrap: tetrap_check,
|
||||
saspecial: saspecial_check,
|
||||
};
|
||||
|
||||
Set.prototype.union = function(setB)
|
||||
function union(setA, setB)
|
||||
{
|
||||
let union = new Set(this);
|
||||
for (let elem of setB)
|
||||
union.add(elem);
|
||||
return union;
|
||||
setA.add(elem);
|
||||
return setA;
|
||||
}
|
||||
|
||||
// Returns a set of objects, each containing the "final form" of a series of deconjugations
|
||||
@@ -585,7 +597,7 @@ function deconjugate(mytext)
|
||||
new_novel.add(newform);
|
||||
}
|
||||
}
|
||||
processed = processed.union(novel);
|
||||
processed = union(processed, novel);
|
||||
novel = new_novel;
|
||||
}
|
||||
|
||||
@@ -596,6 +608,7 @@ function deconjugate(mytext)
|
||||
// building a list of all matches
|
||||
function build_lookup_comb(forms)
|
||||
{
|
||||
console.log("in build_lookup_comb");
|
||||
// FIXME: dumpster fire that shouldn't be anywhere near as complicated as I made it
|
||||
|
||||
// This is the only part of this function that doesn't look like a garbage fire.
|
||||
@@ -644,18 +657,16 @@ function build_lookup_comb(forms)
|
||||
{
|
||||
if(entry.allpos.has(form.tags[form.tags.length-1]))
|
||||
{
|
||||
if(entry.deconj)
|
||||
entry.deconj.add(form);
|
||||
else
|
||||
entry.deconj = new Set([form]);
|
||||
if(entry.deconj === undefined)
|
||||
entry.deconj = new Set();
|
||||
entry.deconj.add(form);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(entry.deconj)
|
||||
entry.deconj.add(form);
|
||||
else
|
||||
entry.deconj = new Set([form]);
|
||||
if(entry.deconj === undefined)
|
||||
entry.deconj = new Set();
|
||||
entry.deconj.add(form);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,6 +681,7 @@ function build_lookup_comb(forms)
|
||||
{
|
||||
if(entry.deconj)
|
||||
{
|
||||
entry.deconj = Array.from(entry.deconj);
|
||||
merger.push(entry);
|
||||
}
|
||||
}
|
||||
@@ -683,6 +695,7 @@ function build_lookup_comb(forms)
|
||||
|
||||
function add_epwing_info(lookups)
|
||||
{
|
||||
console.log("in add_epwing_info");
|
||||
for(let lookup of lookups)
|
||||
{
|
||||
for(let entry of lookup.result)
|
||||
@@ -835,6 +848,7 @@ function add_epwing_info(lookups)
|
||||
entry.epwing["z"] = epwing[0];
|
||||
}
|
||||
}
|
||||
console.log("about to exit add_epwing_info");
|
||||
return lookups;
|
||||
}
|
||||
|
||||
@@ -1010,15 +1024,17 @@ function filter_kana_ish_results(results)
|
||||
return newresults;
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/4459928/how-to-deep-clone-in-javascript
|
||||
function copy(orig)
|
||||
{
|
||||
let mine = orig;
|
||||
|
||||
mine = Object.assign({}, orig)
|
||||
let mine;
|
||||
if (Set.prototype.isPrototypeOf(orig))
|
||||
mine = new Set(orig);
|
||||
else
|
||||
mine = Object.assign({}, orig);
|
||||
for(let f in mine)
|
||||
{
|
||||
f = Object.assign({}, f)
|
||||
if(f !== orig)
|
||||
f = copy(f);
|
||||
}
|
||||
return mine;
|
||||
}
|
||||
@@ -1217,11 +1233,9 @@ function skip_rereferenced_entries(results)
|
||||
let newresults = [];
|
||||
let seenseq = new Set();
|
||||
|
||||
//console.log(results);
|
||||
for(let lookup of results)
|
||||
{
|
||||
let newlookup = [];
|
||||
//console.log(lookup);
|
||||
for(let entry of lookup.result)
|
||||
{
|
||||
if(seenseq.has(entry.seq))
|
||||
@@ -1251,7 +1265,6 @@ function lookup_indirect(text, time, divexisted, alternatives_mode, strict_alter
|
||||
// try to look up successively shorter substrings of text
|
||||
// deconjugate() returns possible deconjugations, one of which has zero deconjugations, i.e. the plain text
|
||||
// build_lookup_comb looks for dictionary definitions matching any deconjugation, returning a list of them
|
||||
//console.log("trying to look up " + text);
|
||||
// FIXME: later lookups using definitions already caught
|
||||
if(alternatives_mode == 0 || alternatives_mode == 1 || alternatives_mode == 2)
|
||||
{
|
||||
@@ -1260,14 +1273,11 @@ function lookup_indirect(text, time, divexisted, alternatives_mode, strict_alter
|
||||
while(result === undefined && text.length > 0)
|
||||
{
|
||||
text = text.substring(0, text.length-1);
|
||||
//console.log("trying to look up " + text);
|
||||
forms = deconjugate(text);
|
||||
result = build_lookup_comb(forms);
|
||||
}
|
||||
if(result !== undefined && result.length > 0)
|
||||
{
|
||||
//console.log("found lookup");
|
||||
//console.log(text)
|
||||
result = sort_results(text, result);
|
||||
if(alternatives_mode == 0 || text.length <= 1)
|
||||
return skip_rereferenced_entries([{text:text, result:result}]);
|
||||
@@ -1473,24 +1483,34 @@ function clipboard_hook(tab)
|
||||
let platform = "";
|
||||
async function get_real_platform()
|
||||
{
|
||||
let platformInfo = await browser.runtime.getPlatformInfo();
|
||||
if(platformInfo)
|
||||
platform = platformInfo.os;
|
||||
console.log(`platform is ${platform}`);
|
||||
if (!ischrome)
|
||||
{
|
||||
let platformInfo = await browser.runtime.getPlatformInfo();
|
||||
if(platformInfo)
|
||||
platform = platformInfo.os;
|
||||
console.log(`platform is ${platform}`);
|
||||
}
|
||||
else
|
||||
{
|
||||
platform = "win";
|
||||
console.log(`on chrome, didn't check platform; assuming desktop`);
|
||||
}
|
||||
}
|
||||
get_real_platform();
|
||||
|
||||
//console.log("setting message listener");
|
||||
browser.runtime.onMessage.addListener((req, sender, sendResponse) =>
|
||||
browser.runtime.onMessage.addListener((req, sender) =>
|
||||
{
|
||||
//console.log("received message to background script");
|
||||
if (req.type == "search")
|
||||
{
|
||||
sendResponse(lookup_indirect(req.text, req.time, req.divexisted, req.alternatives_mode, req.strict_alternatives));
|
||||
let asdf = lookup_indirect(req.text, req.time, req.divexisted, req.alternatives_mode, req.strict_alternatives);
|
||||
console.log("got out of lookup_indirect");
|
||||
console.log(asdf);
|
||||
return Promise.resolve({"response" : asdf});
|
||||
}
|
||||
else if (req.type == "platform")
|
||||
{
|
||||
sendResponse(platform);
|
||||
return Promise.resolve({"response" : platform});
|
||||
}
|
||||
else if (req.type == "fixicon")
|
||||
{
|
||||
@@ -1518,17 +1538,27 @@ browser.runtime.onMessage.addListener((req, sender, sendResponse) =>
|
||||
});
|
||||
xhr.send(req.command);
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
return Promise.resolve(undefined);
|
||||
});
|
||||
//console.log("set message listener");
|
||||
|
||||
browser.contextMenus.create({
|
||||
id: "nazeka-toggle",
|
||||
title: "Toggle Nazeka",
|
||||
contexts: ["page", "selection"],
|
||||
documentUrlPatterns: ["moz-extension://*/reader.html"],
|
||||
onclick: toggle_enabled
|
||||
});
|
||||
if (!ischrome)
|
||||
{
|
||||
browser.contextMenus.create({
|
||||
id: "nazeka-toggle",
|
||||
title: "Toggle Nazeka",
|
||||
contexts: ["page", "selection"],
|
||||
documentUrlPatterns: ["moz-extension://*/reader.html"],
|
||||
onclick: toggle_enabled
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
browser.contextMenus.create({
|
||||
id: "nazeka-toggle",
|
||||
title: "Toggle Nazeka",
|
||||
contexts: ["page", "selection"],
|
||||
documentUrlPatterns: ["chrome-extension://*/reader.html"],
|
||||
onclick: toggle_enabled
|
||||
});
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<html>
|
||||
<head><meta charset="utf-8"/></head>
|
||||
<body>
|
||||
<script src="include/browser-polyfill.min.js" charset="UTF-8"></script>
|
||||
<script src="background-script.js" charset="UTF-8"></script>
|
||||
<textarea id="nazeka-paste-target"></textarea>
|
||||
</body>
|
||||
|
||||
@@ -1016,5 +1016,5 @@
|
||||
"con_tag": "uninflectable",
|
||||
"detail": "slurred"
|
||||
},
|
||||
"// TODO: a bunch of missing contractions, and suppoer for other verb types like vk, vs_i, v5aru, v4r, ..."
|
||||
"// TODO: a bunch of missing contractions, and support for other verb types like vk (くる), vs_i (true する verbs), v5aru (なさる, くださる, etc), v4r (ござる, etc), ..."
|
||||
]
|
||||
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "nazeka",
|
||||
"version": "0.2.4.0",
|
||||
"author": "Wareya",
|
||||
"homepage_url": "https://github.com/wareya/nazeka",
|
||||
"description": "A rikai replacement.",
|
||||
|
||||
"permissions": [
|
||||
"contextMenus",
|
||||
"storage",
|
||||
"tabs",
|
||||
"clipboardRead",
|
||||
"https://assets.languagepod101.com/dictionary/japanese/audiomp3.php?*"
|
||||
],
|
||||
|
||||
"background": {
|
||||
"page": "background.html"
|
||||
},
|
||||
|
||||
"web_accessible_resources": [
|
||||
"include/browser-polyfill.min.js",
|
||||
"img/closebutton24.png",
|
||||
"img/leftarrow24.png",
|
||||
"img/rightarrow24.png",
|
||||
"dict/JMdict1.json",
|
||||
"dict/JMdict2.json",
|
||||
"dict/JMdict3.json",
|
||||
"dict/JMdict4.json",
|
||||
"dict/JMdict5.json",
|
||||
"dict/JMdict6.json",
|
||||
"dict/JMdict7.json",
|
||||
"dict/JMdict8.json",
|
||||
"dict/JMdict9.json",
|
||||
"dict/JMdict10.json",
|
||||
"dict/JMdict11.json",
|
||||
"dict/jdic audio.txt",
|
||||
"dict/deconjugator.json",
|
||||
"reader.js",
|
||||
"reader.html",
|
||||
"mining.js",
|
||||
"mining.html",
|
||||
"livemining.js",
|
||||
"livemining.html",
|
||||
"jmdictabbreviations.html"
|
||||
],
|
||||
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["http://*/*", "https://*/*", "ftp://*/*", "file:///*"],
|
||||
"js": ["include/browser-polyfill.min.js", "texthook.js"],
|
||||
"all_frames": true
|
||||
}
|
||||
],
|
||||
|
||||
"options_ui": {
|
||||
"page": "options.html"
|
||||
},
|
||||
|
||||
"browser_action": {
|
||||
"browser_style": false,
|
||||
"default_icon": {
|
||||
"16": "img/action16.png",
|
||||
"32": "img/action32.png",
|
||||
"512": "img/action512.png"
|
||||
},
|
||||
"default_title": "Nazeka (disabled)",
|
||||
"default_area": "navbar"
|
||||
},
|
||||
|
||||
"icons": {
|
||||
"16": "img/enabled16.png",
|
||||
"32": "img/enabled32.png",
|
||||
"512": "img/enabled512.png"
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@
|
||||
},
|
||||
|
||||
"web_accessible_resources": [
|
||||
"include/browser-polyfill.min.js",
|
||||
"img/closebutton24.png",
|
||||
"img/leftarrow24.png",
|
||||
"img/rightarrow24.png",
|
||||
@@ -54,7 +55,7 @@
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["http://*/*", "https://*/*", "ftp://*/*", "file:///*"],
|
||||
"js": ["texthook.js"],
|
||||
"js": ["include/browser-polyfill.min.js", "texthook.js"],
|
||||
"all_frames": true
|
||||
}
|
||||
],
|
||||
@@ -1,3 +0,0 @@
|
||||
.nazeka_main_keb{font-family: IPAGothic,TakaoGothic,Noto Sans CJK JP Regular,Meiryo,sans-serif;font-size:18px;color:#9DF}
|
||||
.nazeka_main_reb{font-family: IPAGothic,TakaoGothic,Noto Sans CJK JP Regular,Meiryo,sans-serif;font-size:18px;color:#9DF}
|
||||
.nazeka_original{font-style: oblique; float: right; margin-right: 2px; margin-left:2px;}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
#!python
|
||||
from lxml import etree
|
||||
from collections import OrderedDict
|
||||
import json
|
||||
import sys
|
||||
from io import open
|
||||
|
||||
entries = []
|
||||
|
||||
XML_LANG = '{http://www.w3.org/XML/1998/namespace}lang'
|
||||
|
||||
# whether to only output english definitions - if so, glosses are just the gloss text, not a dictionary
|
||||
eng_only = True
|
||||
|
||||
parser = etree.XMLParser(resolve_entities=False)
|
||||
root = etree.parse("JMdict", parser);
|
||||
for ent in root.iter(etree.Entity):
|
||||
if ent.getparent() is not None:
|
||||
if not ent.getparent().text:
|
||||
ent.getparent().text = ""
|
||||
if ent.text:
|
||||
ent.getparent().text += ent.text
|
||||
if ent.tail:
|
||||
ent.getparent().text += ent.tail
|
||||
root = root.getroot();
|
||||
for entry in root.iter("entry"):
|
||||
myentry = OrderedDict()
|
||||
seq = int(entry.find("ent_seq").text)
|
||||
k_eles = []
|
||||
for k_ele in entry.iter("k_ele"):
|
||||
keb = k_ele.find("keb").text
|
||||
ke_infs = []
|
||||
for ke_inf in k_ele.iter("ke_inf"):
|
||||
ke_infs += [ke_inf.text]
|
||||
ke_pris = []
|
||||
for ke_pri in k_ele.iter("ke_pri"):
|
||||
ke_pris += [ke_pri.text]
|
||||
element = OrderedDict()
|
||||
element["keb"] = keb
|
||||
if(len(ke_infs) > 0): element["inf"] = ke_infs
|
||||
if(len(ke_pris) > 0): element["pri"] = ke_pris
|
||||
k_eles += [element]
|
||||
r_eles = []
|
||||
for r_ele in entry.iter("r_ele"):
|
||||
reb = r_ele.find("reb").text
|
||||
re_nokanji = None
|
||||
if r_ele.find("re_nokanji") is not None:
|
||||
re_nokanji = r_ele.find("re_nokanji").text
|
||||
re_restrs = []
|
||||
for re_restr in r_ele.iter("re_restr"):
|
||||
re_restrs += [re_restr.text]
|
||||
re_infs = []
|
||||
for re_inf in r_ele.iter("re_inf"):
|
||||
re_infs += [re_inf.text]
|
||||
re_pris = []
|
||||
for re_pri in r_ele.iter("re_pri"):
|
||||
re_pris += [re_pri.text]
|
||||
element = OrderedDict()
|
||||
element["reb"] = reb
|
||||
if(re_nokanji != None): element["nokanji"] = re_nokanji
|
||||
if(len(re_restrs) > 0): element["restr"] = re_restrs
|
||||
if(len(re_infs) > 0): element["inf"] = re_infs
|
||||
if(len(re_pris) > 0): element["pri"] = re_pris
|
||||
r_eles += [element]
|
||||
senses = []
|
||||
for sense in entry.iter("sense"):
|
||||
stagks = []
|
||||
for stagk in sense.iter("stagk"):
|
||||
stagks += [stagk.text]
|
||||
stagrs = []
|
||||
for stagr in sense.iter("stagr"):
|
||||
stagrs += [stagr.text]
|
||||
poss = []
|
||||
for pos in sense.iter("pos"):
|
||||
#poss += [pos.getchildren()[0].text]
|
||||
poss += [pos.text]
|
||||
xrefs = []
|
||||
for xref in sense.iter("xref"):
|
||||
xrefs += [xref.text]
|
||||
ants = []
|
||||
for ant in sense.iter("ant"):
|
||||
ants += [ant.text]
|
||||
fields = []
|
||||
for field in sense.iter("field"):
|
||||
fields += [field.text]
|
||||
miscs = []
|
||||
for misc in sense.iter("misc"):
|
||||
miscs += [misc.text]
|
||||
s_infs = []
|
||||
for s_inf in sense.iter("s_inf"):
|
||||
s_infs += [s_inf.text]
|
||||
lsources = []
|
||||
for lsource in sense.iter("lsource"):
|
||||
source = OrderedDict()
|
||||
source["text"] = lsource.text
|
||||
source["lang"] = "eng"
|
||||
if lsource.get(XML_LANG): source["lang"] = lsource.get(XML_LANG)
|
||||
source["type"] = "full"
|
||||
if lsource.get("ls_type"): source["type"] = lsource.get("ls_type")
|
||||
source["wasei"] = "n"
|
||||
if lsource.get("ls_wasei"): source["wasei"] = lsource.get("ls_wasei")
|
||||
lsources += [source]
|
||||
dials = []
|
||||
for dial in sense.iter("dial"):
|
||||
dials += [dial.text]
|
||||
glosss = []
|
||||
for gloss in sense.iter("gloss"):
|
||||
definition = OrderedDict()
|
||||
definition["text"] = gloss.text
|
||||
definition["lang"] = "eng"
|
||||
if gloss.get(XML_LANG): definition["lang"] = gloss.get(XML_LANG)
|
||||
if eng_only and definition["lang"] != "eng": continue
|
||||
if eng_only:
|
||||
glosss += [gloss.text]
|
||||
else:
|
||||
glosss += [definition]
|
||||
element = OrderedDict()
|
||||
if(len(stagks) > 0): element["stagk"] = stagks
|
||||
if(len(stagrs) > 0): element["stagr"] = stagrs
|
||||
if(len(poss) > 0): element["pos"] = poss
|
||||
if(len(xrefs) > 0): element["xref"] = xrefs
|
||||
if(len(ants) > 0): element["ant"] = ants
|
||||
if(len(fields) > 0): element["field"] = fields
|
||||
if(len(miscs) > 0): element["misc"] = miscs
|
||||
if(len(s_infs) > 0): element["inf"] = s_infs
|
||||
if(len(lsources) > 0): element["lsource"] = lsources
|
||||
if(len(dials) > 0): element["dial"] = dials
|
||||
if(len(glosss) > 0): element["gloss"] = glosss
|
||||
|
||||
if(len(element) > 0): senses += [element]
|
||||
|
||||
myentry["seq"] = seq
|
||||
if(len(k_eles) > 0): myentry["k_ele"] = k_eles
|
||||
myentry["r_ele"] = r_eles
|
||||
myentry["sense"] = senses
|
||||
entries += [myentry]
|
||||
|
||||
#print(entries)
|
||||
|
||||
#print(json.dumps(entries, ensure_ascii=False))
|
||||
#sys.stdout.buffer.write(json.dumps(entries, ensure_ascii=False, separators=(',',':')).encode("utf-8"))
|
||||
i = 0
|
||||
under = 1
|
||||
copylist = []
|
||||
basename = "JMdict"
|
||||
extension = ".json"
|
||||
limit = 18000
|
||||
for entry in entries:
|
||||
i += 1
|
||||
copylist += [entry]
|
||||
if i >= limit:
|
||||
f = open(basename+str(under)+extension, "w", newline="\n", encoding="utf-8")
|
||||
f.write(json.dumps(copylist, ensure_ascii=False, separators=(',',':')));
|
||||
copylist = []
|
||||
i = 0
|
||||
under += 1
|
||||
|
||||
f = open(basename+str(under)+extension, "w", newline="\n", encoding="utf-8")
|
||||
f.write(json.dumps(copylist, ensure_ascii=False, separators=(',',':')));
|
||||
|
||||
|
||||
Vendored
+1186
File diff suppressed because it is too large.
Load diff
@@ -4,6 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Nazeka: Configuration for Live Mining</title>
|
||||
<script src="include/browser-polyfill.min.js" charset="UTF-8"></script>
|
||||
<script type="text/javascript" src="livemining.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -11,6 +11,7 @@ body
|
||||
font-size: 1em;
|
||||
}
|
||||
</style>
|
||||
<script src="include/browser-polyfill.min.js" charset="UTF-8"></script>
|
||||
<script src="mining.js" charset="UTF-8"></script>
|
||||
</head>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>Nazeka: options</title>
|
||||
<script src="include/browser-polyfill.min.js" charset="UTF-8"></script>
|
||||
<script type="text/javascript" src="options.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
+8
-2
@@ -77,8 +77,14 @@ function defaults()
|
||||
settings.push({
|
||||
id: "ignore_linebreaks",
|
||||
kind: "checkbox",
|
||||
default: true,
|
||||
label: "Ignore hard line breaks (disable for text with preformatted linewraps)"
|
||||
});
|
||||
settings.push({
|
||||
id: "ignore_divs",
|
||||
kind: "checkbox",
|
||||
default: false,
|
||||
label: "Ignore hard line breaks"
|
||||
label: "Search out from within block-like elements like divs (enable only for very poorly-constructed web pages; usually causes performance problems)"
|
||||
});
|
||||
settings.push({
|
||||
id: "live_mining",
|
||||
@@ -146,7 +152,7 @@ function defaults()
|
||||
id: "fixedwidthpositioning",
|
||||
kind: "checkbox",
|
||||
default: false,
|
||||
label: "Position as though fixed width"
|
||||
label: "Position as though fixed width (currently nonfunctional; will fix later)"
|
||||
});
|
||||
settings.push({
|
||||
id: "corner",
|
||||
|
||||
@@ -20,6 +20,7 @@ p
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
<script src="include/browser-polyfill.min.js" charset="UTF-8"></script>
|
||||
<script src="reader.js" charset="UTF-8"></script>
|
||||
</head>
|
||||
|
||||
|
||||
+11
-5
@@ -1,10 +1,12 @@
|
||||
Nazeka is a rikai replacement.
|
||||
|
||||
*Nazeka is not ready for general use yet; it does not yet have all the necessary behaviors that rikai variants have.*
|
||||
*(Nazeka is not ready for general use yet; it does not yet have all the necessary behaviors that rikai variants have.**
|
||||
|
||||
This is my first nontrivial javascript work and the code is probably terrible.
|
||||
|
||||
Options:
|
||||
# Options
|
||||
|
||||
Nazeka has added many options since it was first created, and they're documented within the options page. The following is an example of what options it has:
|
||||
|
||||
- Enabled: whether to search pages for text
|
||||
- Compact: definitions on same line or with linebreaks
|
||||
@@ -24,13 +26,17 @@ Options:
|
||||
|
||||
Nazeka has added more options since this was written.
|
||||
|
||||
Building:
|
||||
# Building
|
||||
|
||||
Build process requires python and lxml, or an existing copy of the extension to rip JMdict#.json from.
|
||||
|
||||
- Copy the appropriate manifest.json from etc/ (either etc/firefox/manifest.json or etc/chrome/manifest.json) into the root of the repository
|
||||
- Download JMdict.gz from http://www.edrdg.org/jmdict/edict_doc.html
|
||||
- Convert it to json with https://gist.github.com/wareya/c2175520db5f1927e4f6ba839487dd8c
|
||||
- Place under dict/ so that [...]/dict/JMdict1.json and others exist in that location relative to [...]/manifest.json
|
||||
- Convert it to json with etc/process.py
|
||||
- Move the output to under dict/ so that [...]/dict/JMdict1.json and others exist in that location relative to [...]/manifest.json
|
||||
- Make sure every .json file is listed as available to the extension in manifest.json - if jmdict added a lot of words, there might be more than 11 files now
|
||||
- Package as an extension for your browser of choice, or load it as a temporary/indev extension using your browser's development tools
|
||||
|
||||
# Copyright and License
|
||||
|
||||
Copyright 2017~2018; Licensed under the Apache License, Version 2.0: https://www.apache.org/licenses/LICENSE-2.0
|
||||
+102
-105
@@ -14,6 +14,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
if (navigator.userAgent.indexOf('Chrome') > -1)
|
||||
{
|
||||
var ischrome = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var ischrome = false;
|
||||
}
|
||||
|
||||
'use strict';
|
||||
|
||||
// updated by a timer looping function, based on local storage set by the options page
|
||||
@@ -41,7 +50,8 @@ hlfont: "",
|
||||
corner: 0,
|
||||
xoffset: 5,
|
||||
yoffset: 22,
|
||||
ignore_linebreaks: false,
|
||||
ignore_linebreaks: true,
|
||||
ignore_divs: false,
|
||||
sticky: false,
|
||||
popup_follows_mouse: true,
|
||||
popup_requires_key: 0, // 0: none; 1: ctrl; 2: shift
|
||||
@@ -66,11 +76,15 @@ async function get_real_platform()
|
||||
let my_platform = undefined;
|
||||
try {
|
||||
my_platform = await browser.runtime.sendMessage({type:"platform"});
|
||||
if(my_platform)
|
||||
my_platform = my_platform["response"];
|
||||
}catch(err){}
|
||||
while(my_platform == "")
|
||||
{
|
||||
try {
|
||||
my_platform = await browser.runtime.sendMessage({type:"platform"});
|
||||
if(my_platform)
|
||||
my_platform = my_platform["response"];
|
||||
}catch(err){}
|
||||
}
|
||||
platform = my_platform;
|
||||
@@ -1023,7 +1037,8 @@ async function settings_init()
|
||||
getvar("xoffset", 5);
|
||||
getvar("yoffset", 22);
|
||||
|
||||
getvar("ignore_linebreaks", false);
|
||||
getvar("ignore_linebreaks", true);
|
||||
getvar("ignore_divs", false);
|
||||
getvar("sticky", false);
|
||||
getvar("popup_follows_mouse", true);
|
||||
getvar("popup_requires_key", 0);
|
||||
@@ -1072,100 +1087,67 @@ browser.storage.onChanged.addListener((updates, storageArea) =>
|
||||
}
|
||||
});
|
||||
|
||||
// look up words on a timer loop that only uses the most recent lookup request and ignores all the others
|
||||
|
||||
let lookup_timer = undefined;
|
||||
let lookup_queue = [];
|
||||
//let lookup_rate = 8;
|
||||
|
||||
let last_lookup = [];
|
||||
|
||||
let last_lookup = undefined;
|
||||
let last_manual_interaction = Date.now();
|
||||
|
||||
let lookup_loop_cancel = false;
|
||||
let lookup_last_time = Date.now();
|
||||
|
||||
async function lookup_loop()
|
||||
async function send_lookup(lookup)
|
||||
{
|
||||
//console.log("running lookup queue");
|
||||
lookup_last_time = Date.now();
|
||||
let t_start = Date.now();
|
||||
if(lookup_queue.length > 0)
|
||||
{
|
||||
//console.log("queue not empty");
|
||||
let lookup = lookup_queue.pop();
|
||||
lookup_queue = [];
|
||||
last_lookup = lookup;
|
||||
//console.log("asking background to search the dictionary");
|
||||
let response = await browser.runtime.sendMessage({type:"search", text:lookup[0], time:Date.now(), divexisted:exists_div(), alternatives_mode:settings.alternatives_mode, strict_alternatives:settings.strict_alternatives});
|
||||
//console.log("got response");
|
||||
if(response && response != "itsthesame")
|
||||
{
|
||||
if(!response.length)
|
||||
{
|
||||
let mydiv = build_div(response.text, response.result, lookup[5], lookup[6]);
|
||||
if(mydiv)
|
||||
display_div(mydiv, lookup[3], lookup[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
let mydiv = build_div_compound(response, lookup[5], lookup[6]);
|
||||
if(mydiv)
|
||||
display_div(mydiv, lookup[3], lookup[4]);
|
||||
}
|
||||
}
|
||||
//else if(response != "itsthesame" && settings.popup_follows_mouse && exists_div() && !lastMoreText.includes(lookup[0].substring(0, Math.max(0, lookup[0].length-2))))
|
||||
else if(response != "itsthesame" && exists_div() && !lastMoreText.includes(lookup[0].substring(0, Math.max(1, lookup[0].length-2))))
|
||||
lookup_cancel();
|
||||
}
|
||||
let t_end = Date.now();
|
||||
let t_to_wait = settings.lookuprate - (t_end - t_start);
|
||||
if(t_to_wait < 0) t_to_wait = 0;
|
||||
if(t_to_wait > settings.lookuprate) t_to_wait = settings.lookuprate;
|
||||
last_lookup = lookup;
|
||||
|
||||
if(lookup_loop_cancel)
|
||||
let response = await browser.runtime.sendMessage(
|
||||
{
|
||||
//console.log("queue setup");
|
||||
lookup_loop_cancel = false;
|
||||
lookup_timer = undefined;
|
||||
return;
|
||||
type:"search",
|
||||
text:lookup[0],
|
||||
time:Date.now(),
|
||||
divexisted:exists_div(),
|
||||
alternatives_mode:settings.alternatives_mode,
|
||||
strict_alternatives:settings.strict_alternatives
|
||||
});
|
||||
if(response)
|
||||
response = response["response"];
|
||||
|
||||
if(response && response != "itsthesame")
|
||||
{
|
||||
if(!response.length)
|
||||
{
|
||||
let mydiv = build_div(response.text, response.result, lookup[5], lookup[6]);
|
||||
if(mydiv)
|
||||
display_div(mydiv, lookup[3], lookup[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
let mydiv = build_div_compound(response, lookup[5], lookup[6]);
|
||||
if(mydiv)
|
||||
display_div(mydiv, lookup[3], lookup[4]);
|
||||
}
|
||||
}
|
||||
else
|
||||
lookup_timer = setTimeout(lookup_loop, t_to_wait);
|
||||
else if(response != "itsthesame" && exists_div() && !lastMoreText.includes(lookup[0].substring(0, Math.max(1, lookup[0].length-2))))
|
||||
lookup_cancel();
|
||||
}
|
||||
|
||||
lookup_timer = setTimeout(lookup_loop, settings.lookuprate);
|
||||
|
||||
function lookup_enqueue(text, x, y, x2, y2, moreText, index)
|
||||
{
|
||||
//console.log("trying to enqueue lookup");
|
||||
lookup_queue = [[text, x, y, x2, y2, moreText, index]];
|
||||
//console.log("enqueued lookup");
|
||||
if(!lookup_timer || lookup_last_time+settings.lookuprate*100 < Date.now())
|
||||
if(lookup_last_time+settings.lookuprate < Date.now())
|
||||
{
|
||||
if(lookup_timer)
|
||||
clearTimeout(lookup_timer);
|
||||
lookup_timer = setTimeout(lookup_loop, settings.lookuprate);
|
||||
send_lookup([text, x, y, x2, y2, moreText, index]);
|
||||
}
|
||||
}
|
||||
|
||||
function lookup_cancel()
|
||||
{
|
||||
lookup_queue = [];
|
||||
if(!settings.sticky || get_doc().body.getElementsByClassName("nazeka_mining_ui").length != 0 || platform == "android")
|
||||
delete_div();
|
||||
}
|
||||
|
||||
function manual_close()
|
||||
{
|
||||
lookup_queue = [];
|
||||
delete_div();
|
||||
last_manual_interaction = Date.now();
|
||||
}
|
||||
|
||||
function lookup_cancel_force()
|
||||
{
|
||||
lookup_queue = [];
|
||||
delete_div();
|
||||
}
|
||||
|
||||
@@ -1183,8 +1165,8 @@ function lookup_left()
|
||||
index--;
|
||||
text = text.substring(index);
|
||||
|
||||
lookup_queue = [[text, last_lookup[1], last_lookup[2], last_lookup[3], last_lookup[4], last_lookup[5], index]];
|
||||
last_manual_interaction = Date.now();
|
||||
send_lookup([text, last_lookup[1], last_lookup[2], last_lookup[3], last_lookup[4], last_lookup[5], index]);
|
||||
}
|
||||
|
||||
function lookup_right()
|
||||
@@ -1198,8 +1180,8 @@ function lookup_right()
|
||||
index++;
|
||||
text = text.substring(index);
|
||||
|
||||
lookup_queue = [[text, last_lookup[1], last_lookup[2], last_lookup[3], last_lookup[4], last_lookup[5], index]];
|
||||
last_manual_interaction = Date.now();
|
||||
send_lookup([text, last_lookup[1], last_lookup[2], last_lookup[3], last_lookup[4], last_lookup[5], index]);
|
||||
}
|
||||
|
||||
let time_of_last = Date.now();
|
||||
@@ -1250,18 +1232,25 @@ function grab_more_text(textNode, direction = 1)
|
||||
iters += 1;
|
||||
if(current_node == undefined) break;
|
||||
// search up parent element only if current element is inline-like
|
||||
try
|
||||
if (!settings.ignore_divs)
|
||||
{
|
||||
let display = getComputedStyle(current_node).display;
|
||||
let tagname = current_node.tagName.toLowerCase();
|
||||
// FIXME get real inline vs block detection
|
||||
if(!(display.contains("inline") || display == "ruby") || tagname == "rt" || tagname == "rp")
|
||||
try
|
||||
{
|
||||
break;
|
||||
let display = getComputedStyle(current_node).display;
|
||||
let tagname = current_node.tagName.toLowerCase();
|
||||
// FIXME get real inline vs block detection
|
||||
|
||||
let inline_like = display.includes("inline") || display == "ruby";
|
||||
|
||||
let ruby_interior = tagname == "rt" || tagname == "rp";
|
||||
console.log(display);
|
||||
console.log(inline_like);
|
||||
console.log(ruby_interior);
|
||||
if(ruby_interior || !inline_like)
|
||||
break;
|
||||
}
|
||||
catch(err){}
|
||||
}
|
||||
catch(err){}
|
||||
|
||||
if(iters > 100)
|
||||
{
|
||||
console.log("too many iterations");
|
||||
@@ -1272,6 +1261,8 @@ function grab_more_text(textNode, direction = 1)
|
||||
let parent = current_node.parentNode;
|
||||
if(parent == undefined || parent == current_node) break;
|
||||
let i = Array.prototype.indexOf.call(current_node.parentNode.childNodes, current_node);
|
||||
console.log(current_node);
|
||||
console.log(i);
|
||||
if(i < 0) break;
|
||||
i += direction;
|
||||
while(i < current_node.parentNode.childNodes.length && i >= 0 && text.length < settings.contextlength && (!text.includes("\n") || settings.ignore_linebreaks))
|
||||
@@ -1373,6 +1364,16 @@ function grab_text(textNode, offset, elemental)
|
||||
return [text, moreText, index];
|
||||
}
|
||||
|
||||
function true_next_sibling(node)
|
||||
{
|
||||
if(node === null)
|
||||
return null;
|
||||
if(node.nextSibling !== null)
|
||||
return node.nextSibling;
|
||||
else
|
||||
return true_next_sibling(node.parentNode);
|
||||
}
|
||||
|
||||
let last_seen_event = undefined;
|
||||
let shift_down = false;
|
||||
let ctrl_down = false;
|
||||
@@ -1448,6 +1449,7 @@ function update(event)
|
||||
yoffset = searchoffset;
|
||||
else
|
||||
xoffset = searchoffset;
|
||||
// firefox
|
||||
if (document.caretPositionFromPoint)
|
||||
{
|
||||
let caretdata = document.caretPositionFromPoint(x+xoffset, y+yoffset);
|
||||
@@ -1462,14 +1464,28 @@ function update(event)
|
||||
range.detach();
|
||||
}
|
||||
}
|
||||
// chrome
|
||||
else if (document.caretRangeFromPoint)
|
||||
{
|
||||
let range = document.caretRangeFromPoint(x+xoffset, y+yoffset);
|
||||
if(range)
|
||||
{
|
||||
try
|
||||
{
|
||||
range.setEnd(range.endContainer, range.endOffset+1);
|
||||
}
|
||||
catch(err)
|
||||
{
|
||||
try
|
||||
{
|
||||
range.setEnd(true_next_sibling(range.endContainer), 0);
|
||||
}
|
||||
catch(err){}
|
||||
}
|
||||
textNode = range.startContainer;
|
||||
offset = range.startOffset;
|
||||
hitrect = range.getBoundingClientRect();
|
||||
console.log(hitrect);
|
||||
}
|
||||
}
|
||||
if(ele && !ele.contains(textNode) && platform != "android" && (!settings.sticky || get_doc().body.getElementsByClassName("nazeka_mining_ui").length != 0)) // sticky mode and android need to break out on parent detection
|
||||
@@ -1498,7 +1514,7 @@ function update(event)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!(textNode == undefined))
|
||||
if(textNode !== undefined)
|
||||
{
|
||||
// we hit an node, see if it's a transparent element and try to move it under everything temporarily if it is
|
||||
try
|
||||
@@ -1533,9 +1549,6 @@ function update(event)
|
||||
let elemental = acceptable_element(textNode);
|
||||
if (textNode && (textNode.nodeType == 3 || elemental))
|
||||
{
|
||||
//print_object(textNode);
|
||||
//print_object(textNode.parentNode);
|
||||
|
||||
let rect = undefined;
|
||||
let fud = 5;
|
||||
if(elemental)
|
||||
@@ -1544,13 +1557,15 @@ function update(event)
|
||||
rect = textNode.parentNode.getBoundingClientRect();
|
||||
|
||||
// FIXME: Doesn't work to reject in all cases
|
||||
|
||||
let hit = (event.clientX+fud >= rect.left && event.clientX-fud <= rect.right && event.clientY+fud >= rect.top && event.clientY-fud <= rect.bottom);
|
||||
//let hit = (event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom);
|
||||
if(!hit)
|
||||
if(!ischrome)
|
||||
{
|
||||
lookup_cancel();
|
||||
return;
|
||||
let hit = (event.clientX+fud >= rect.left && event.clientX-fud <= rect.right && event.clientY+fud >= rect.top && event.clientY-fud <= rect.bottom);
|
||||
//let hit = (event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom);
|
||||
if(!hit)
|
||||
{
|
||||
lookup_cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let found = grab_text(textNode, offset, elemental);
|
||||
@@ -1558,33 +1573,15 @@ function update(event)
|
||||
let moreText = found[1];
|
||||
let index = found[2];
|
||||
|
||||
//text = text.trim();
|
||||
|
||||
//print_object(text);
|
||||
text = text.substring(0, Math.min(text.length, settings.length));
|
||||
|
||||
//if(text != "")
|
||||
//lookup_indirect(text, event.clientX, event.clientY, time_of_last);
|
||||
if(text != "")
|
||||
{
|
||||
//console.log("calling lookup_enqueue");
|
||||
lookup_enqueue(text, event.clientX, event.clientY, event.pageX, event.pageY, moreText, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
// console.log("no text");
|
||||
lookup_cancel();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// console.log("no text node");
|
||||
// console.log("actual type:");
|
||||
// console.log(textNode.nodeType);
|
||||
// console.log("offset:");
|
||||
// console.log(offset);
|
||||
lookup_cancel();
|
||||
}
|
||||
}
|
||||
|
||||
function update_touch(event)
|
||||
|
||||
Reference in new issue
Block a user