comment maintainence and refactor the restriction code into a single function in background-script

This commit is contained in:
wareya committed 2018-01-30 20:06:58 -05:00
1 parent 6fc55999de
commit 33725e603f
2 files changed
+268 -211

No files matched your search

+163 -2
View File
@@ -13,7 +13,6 @@ let epwing = [
let lookup_epwing_kan = new Map(); let lookup_epwing_kan = new Map();
let lookup_epwing_kana = new Map(); let lookup_epwing_kana = new Map();
function string_is_kana(str) function string_is_kana(str)
{ {
for(let i = 0; i < str.length; i++) for(let i = 0; i < str.length; i++)
@@ -1042,6 +1041,168 @@ function filter_kana_ish_results(results)
return newresults; return newresults;
} }
// https://stackoverflow.com/questions/4459928/how-to-deep-clone-in-javascript
function copy(orig)
{
let mine = orig;
mine = Object.assign({}, orig)
for(let f in mine)
{
f = Object.assign({}, f)
}
return mine;
}
// Restrict the listed spellings/readings of a JMdict entry to the ones allowed by the looked-up text.
function restrict_by_text(entry, text)
{
// deep clone lol (we should probably do this WAY earlier)
let term = copy(entry);
//console.log(entry);
//console.log(term);
if(!term.found) // bogus lookup
return term;
// Example restrictions:
// ゆう: 夕 only
// さくや: 昨夜 only
// evening: 夕・夕べ only
// last night: ゆうべ・さくや only
// Derived:
// 昨夜: さくや・ゆうべ only
// 夕: ゆう・ゆうべ only
// 夕べ: ゆうべ only
// evening: ゆう・ゆうべ only
// last night: 夕べ・昨夜 only
// if we didn't look up kanji, look for the first fitting kanji spellings in the entry (they're ordered sensibly) if there are kanji spellings
term.orig_found = term.found;
if(!!(term.found.reb) && term.k_ele)
{
let r_restr = undefined;
// kanji to which the reb is restricted
if(term.found.restr && term.found.restr.length > 0)
r_restr = term.found.restr;
if(!r_restr)
r_restr = [];
// find the first kanji-including spelling that isn't restricted to readings that aren't the one we looked up
for(let j = 0; j < term.k_ele.length; j++)
{
// if this spelling is restricted to particular readings
if(term.k_ele[j].restr)
{
for(let l = 0; l < term.k_ele[j].restr.length; l++)
{
// if the reading we looked up is one of the ones it's restricted to
// if the reading we looked up isn't restricted to spellings other than this one
if(term.k_ele[j].restr[l] == term.found.reb && (r_restr.length == 0 || r_restr.indexOf(term.k_ele[j].keb) > -1))
{
// pretend we looked up this spelling
term.found = term.k_ele[j];
break;
}
}
}
// if the spelling does not have restrictions
// if the reading is not restricted to other spellings
else if(r_restr.length == 0 || r_restr.indexOf(term.k_ele[j].keb) > -1)
{
// pretend we looked up this spelling
term.found = term.k_ele[j];
break;
}
}
}
// eliminate unfitting kanji spellings if we originally looked up a reading
if(!!(term.orig_found.reb) && term.k_ele)
{
let r_restr = undefined;
// kanji to which the reb is restricted
if(term.orig_found.restr && term.orig_found.restr.length > 0)
r_restr = term.orig_found.restr;
else
r_restr = [];
let new_k_ele = [];
for(let j = 0; j < term.k_ele.length; j++)
{
if(r_restr.length > 0 && r_restr.indexOf(term.k_ele[j].keb) < 0)
continue;
// if this spelling is restricted to particular readings
if(term.k_ele[j].restr)
{
for(let l = 0; l < term.k_ele[j].restr.length; l++)
// if the reading we looked up is one of the ones it's restricted to
// if the reading we looked up isn't restricted to spellings other than this one
if(term.k_ele[j].restr[l] == term.orig_found.reb)
new_k_ele.push(term.k_ele[j]);
}
// if the spelling does not have restrictions
// if the reading is not restricted to other spellings
else
new_k_ele.push(term.k_ele[j]);
}
term.k_ele = new_k_ele;
}
// eliminate unfitting readings if we originally looked up a spelling
if(!!(term.orig_found.keb) && term.r_ele)
{
let k_restr = undefined;
// kanji to which the reb is restricted
if(term.orig_found.restr && term.orig_found.restr.length > 0)
k_restr = term.orig_found.restr;
else
k_restr = [];
let new_r_ele = [];
for(let j = 0; j < term.r_ele.length; j++)
{
if(k_restr.length > 0 && k_restr.indexOf(term.r_ele[j].reb) < 0)
continue;
if(term.r_ele[j].restr)
{
for(let l = 0; l < term.r_ele[j].restr.length; l++)
if(term.r_ele[j].restr[l] == term.orig_found.keb)
new_r_ele.push(term.r_ele[j]);
}
else
new_r_ele.push(term.r_ele[j]);
}
term.r_ele = new_r_ele;
}
// eliminate unfitting definitions for the original lookup
if(term.sense)
{
let new_sense = [];
for(let j = 0; j < term.sense.length; j++)
{
if(term.orig_found.keb && term.sense[j].stagk)
{
for(let l = 0; l < term.sense[j].stagk.length; l++)
if(term.sense[j].stagk[l] == term.orig_found.keb)
new_sense.push(term.sense[j]);
}
else if(term.orig_found.reb && term.sense[j].stagr)
{
for(let l = 0; l < term.sense[j].stagr.length; l++)
if(term.sense[j].stagr[l] == term.orig_found.reb)
new_sense.push(term.sense[j]);
}
// if the spelling does not have restrictions
// if the reading is not restricted to other spellings
else
new_sense.push(term.sense[j]);
}
term.sense = new_sense;
}
return term;
}
// Skip JMdict entries reappearing in alternative lookups (so only the first one is shown)
function skip_rereferenced_entries(results) function skip_rereferenced_entries(results)
{ {
let newresults = []; let newresults = [];
@@ -1057,7 +1218,7 @@ function skip_rereferenced_entries(results)
if(seenseq.has(entry.seq)) if(seenseq.has(entry.seq))
continue; continue;
seenseq.add(entry.seq); seenseq.add(entry.seq);
newlookup.push(entry); newlookup.push(restrict_by_text(entry, lookup.text));
} }
if(newlookup.length > 0) if(newlookup.length > 0)
newresults.push({text:lookup.text, result:newlookup}); newresults.push({text:lookup.text, result:newlookup});
+105 -209
View File
@@ -18,6 +18,7 @@
'use strict'; 'use strict';
// updated by a timer looping function, based on local storage set by the options page
let settings = { let settings = {
enabled: false, enabled: false,
compact: true, compact: true,
@@ -44,8 +45,10 @@ yoffset: 22
let last_time_display = Date.now(); let last_time_display = Date.now();
// FIXME: this should be the extension ID or a per-page random string, but it's not useful to change this yet, not until firefox lands shadow DOM
let div_class = "nazeka_fGKRTDGFGgr9atT"; let div_class = "nazeka_fGKRTDGFGgr9atT";
// the popup is inserted into the page as a screen-relative div, we never delete it because modifying the root DOM of very long pages is expensive, we hide it instead
let last_displayed = undefined; let last_displayed = undefined;
function delete_div () function delete_div ()
{ {
@@ -59,14 +62,11 @@ function delete_div ()
} }
} }
// here we set all the styling and positioning of the div, passing "middle" as the actual contents of it.
// this is rather elaborate because of 1) a lack of shadow DOM, even for just styling 2) options 3) """features""" of how HTML viewport stuff works that are actually terrible
function display_div (middle, x, y, time) function display_div (middle, x, y, time)
{ {
//let bordercolor = undefined; let font = settings.font.trim().replace(";","").replace("}","");
//if(settings.superborder)
// bordercolor = "white";
//else
// bordercolor = "#CCC";
let font = settings.font.trim().replace(";","");
if(font != "") if(font != "")
font += ","; font += ",";
middle.style = `background-color: ${settings.bgcolor}; border-radius: 2.5px; border: 1px solid ${settings.bgcolor};`; middle.style = `background-color: ${settings.bgcolor}; border-radius: 2.5px; border: 1px solid ${settings.bgcolor};`;
@@ -235,14 +235,18 @@ function clip(str)
return str.substring(1, str.length-1); return str.substring(1, str.length-1);
} }
// Here we actually build the content of the lookup popup, based on the text we looked up and the list of lookups from the background script
// note that we can get multiple lookups and this function only handles a single lookup
function build_div_inner (text, result) function build_div_inner (text, result)
{ {
//console.log("building div for " + text); //console.log("building div for " + text);
//console.log(result); //console.log(result);
let temp = document.createElement("div"); let temp = document.createElement("div");
temp.style.position = "relative"; temp.style.position = "relative";
// the "Looked up XXXX" text
if(settings.showoriginal) if(settings.showoriginal)
{ {
// nesting it like this lets us access nazeka_lookup when we want to get the text we looked up, if we have text in front of it, which we don't anymore
let original = document.createElement("div"); let original = document.createElement("div");
original.className = "nazeka_original"; original.className = "nazeka_original";
//original.textContent = "Looked up "; //original.textContent = "Looked up ";
@@ -262,13 +266,14 @@ function build_div_inner (text, result)
temp.appendChild(original_inner); temp.appendChild(original_inner);
} }
// styling for highlighted stuff and the lookup text
let style = document.createElement("style"); let style = document.createElement("style");
style.type = "text/css"; style.type = "text/css";
let font = settings.hlfont.trim(); let font = settings.hlfont.trim().replace(";","").replace("}","");
if(font != "") if(font != "")
font += ","; font += ",";
if(settings.font.trim().replace(";","") != "") if(settings.font.trim().replace(";","").replace("}","") != "")
font += settings.font.trim().replace(";","") + ","; font += settings.font.trim().replace(";","").replace("}","") + ",";
style.textContent = style.textContent =
`.nazeka_main_keb{font-family: ${font}IPAGothic,TakaoGothic,Noto Sans CJK JP Regular,Meiryo,sans-serif;font-size:18px;color:${settings.hlcolor}}\ `.nazeka_main_keb{font-family: ${font}IPAGothic,TakaoGothic,Noto Sans CJK JP Regular,Meiryo,sans-serif;font-size:18px;color:${settings.hlcolor}}\
.nazeka_main_reb{font-family: ${font}IPAGothic,TakaoGothic,Noto Sans CJK JP Regular,Meiryo,sans-serif;font-size:18px;color:${settings.hlcolor}}\ .nazeka_main_reb{font-family: ${font}IPAGothic,TakaoGothic,Noto Sans CJK JP Regular,Meiryo,sans-serif;font-size:18px;color:${settings.hlcolor}}\
@@ -280,9 +285,6 @@ function build_div_inner (text, result)
for(let i = 0; i < result.length; i++) for(let i = 0; i < result.length; i++)
{ {
let term = result[i]; let term = result[i];
// shouldn't happen but just in case of broken data
if(!term.found)
continue;
let container = document.createElement("div"); let container = document.createElement("div");
container.className = "nazeka_word_container"; container.className = "nazeka_word_container";
@@ -299,206 +301,125 @@ function build_div_inner (text, result)
let temptag = document.createElement("span"); let temptag = document.createElement("span");
temptag.className = "nazeka_word"; temptag.className = "nazeka_word";
let found_kanji = true;
let original_kana = ""; let original_kana = "";
if(term.found.reb) if(term.found.reb)
original_kana = term.found.reb; original_kana = term.found.reb;
if(term.k_ele) if(term.found.keb)
{ {
let looked_up_kanji = !!(term.found.keb); let k_ele = term.found;
let kanji_text = k_ele.keb;
let keb = document.createElement("span");
keb.className = "nazeka_main_keb";
keb.textContent = kanji_text;
temptag.appendChild(keb);
let r_restr = []; // list readings
// if we didn't look up kanji, look for the first fitting kanji in the entry (they're ordered sensibly) let readings = term.r_ele;
if(!looked_up_kanji)
if(term.deconj)
{ {
if(term.found.restr && term.found.restr.length > 0) //console.log(term.deconj);
r_restr = term.found.restr; let deconj = "";
if(!r_restr) let first = true;
r_restr = []; for(let form of term.deconj)
// find the first kanji that isn't restricted to readings that aren't the one we looked up
for(let j = 0; j < term.k_ele.length; j++)
{ {
if(term.k_ele[j].restr) let formtext = "";
let added = 0;
for(let f = form.process.length-1; f >= 0; f--)
{ {
for(let l = 0; l < term.k_ele[j].restr.length; l++) let info = form.process[f];
{ if(info == "")
if(term.k_ele[j].restr[l] == text) continue;
{ if(info.startsWith("(") && info.endsWith(")") && f != 0)
if(r_restr.length == 0 || r_restr.indexOf(term.k_ele[j].keb) > -1) continue;
{ if(added > 0)
term.found = term.k_ele[j]; formtext += "―";
//console.log("reassigned found") added++;
//console.log(term.found); formtext += info;
found_kanji = true;
break;
}
}
}
} }
else if(formtext != "")
{ {
if(r_restr.length == 0 || r_restr.indexOf(term.k_ele[j].keb) > -1) if(first)
{ deconj += "~";
term.found = term.k_ele[j]; else
//console.log("reassigned found") deconj += "・";
//console.log(term.found); deconj += formtext;
found_kanji = true;
break;
}
} }
first = false;
} }
temptag.appendChild(document.createTextNode(deconj));
} }
else if(k_ele.inf)
found_kanji = true;
if(found_kanji)
{ {
let k_ele = term.found; let maininfos = document.createElement("span");
let kanji_text = k_ele.keb; maininfos.className = "nazeka_main_infos";
let keb = document.createElement("span"); for(let info of k_ele.inf)
keb.className = "nazeka_main_keb";
keb.textContent = kanji_text;
temptag.appendChild(keb);
// list readings
let readings = [];
// don't list readings if restricted to kanji we didn't look up
for(let j = 0; j < term.r_ele.length; j++)
{ {
let r = term.r_ele[j]; let keb_inf = document.createElement("span");
let invalid = r.restr != undefined; keb_inf.className = "nazeka_main_inf";
if(r.restr) keb_inf.textContent += "(";
{ keb_inf.textContent += clip(info);
for(let l = 0; l < r.restr.length; l++) keb_inf.textContent += ")";
if(r.restr[l] == kanji_text) maininfos.appendChild(keb_inf);
invalid = false;
}
if(!invalid)
readings.push(term.r_ele[j]);
} }
if(term.deconj) temptag.appendChild(maininfos);
}
temptag.appendChild(document.createTextNode(" 《"));
let e_readings = document.createElement("span");
e_readings.className = "nazeka_readings";
for(let j = 0; j < readings.length; j++)
{
e_readings.appendChild(document.createTextNode(readings[j].reb));
if(readings[j].inf)
{ {
let deconj = ""; for(let info of readings[j].inf)
let first = true;
for(let form of term.deconj)
{ {
let formtext = ""; let reb_inf = document.createElement("span");
let added = 0; reb_inf.className = "nazeka_reb_inf";
for(let f = form.process.length-1; f >= 0; f--) reb_inf.textContent += "(";
{ reb_inf.textContent += clip(info);
let info = form.process[f]; reb_inf.textContent += ")";
if(info == "") e_readings.appendChild(reb_inf);
continue;
if(info.startsWith("(") && info.endsWith(")") && f != 0)
continue;
if(added > 0)
formtext += "―";
added++;
formtext += info;
}
if(formtext != "")
{
if(first)
deconj += "~";
else
deconj += "・";
deconj += formtext;
}
first = false;
} }
temptag.appendChild(document.createTextNode(deconj));
} }
if(k_ele.inf) if(j+1 != readings.length)
e_readings.appendChild(document.createTextNode("・"));
}
temptag.appendChild(e_readings);
temptag.appendChild(document.createTextNode("》"));
// list alternatives
let alternatives = [];
for(let j = 0; j < term.k_ele.length; j++)
if(term.k_ele[j].keb != kanji_text)
alternatives.push(term.k_ele[j]);
if(alternatives.length > 0)
temptag.appendChild(document.createTextNode(" (also "));
for(let j = 0; j < alternatives.length; j++)
{
temptag.appendChild(document.createTextNode(alternatives[j].keb));
if(alternatives[j].inf)
{ {
let maininfos = document.createElement("span"); for(let info of alternatives[j].inf)
maininfos.className = "nazeka_main_infos";
for(let info of k_ele.inf)
{ {
temptag.appendChild(document.createTextNode(" "));
let keb_inf = document.createElement("span"); let keb_inf = document.createElement("span");
keb_inf.className = "nazeka_main_inf"; keb_inf.className = "nazeka_keb_inf";
keb_inf.textContent += "("; keb_inf.textContent += "(";
keb_inf.textContent += clip(info); keb_inf.textContent += clip(info);
keb_inf.textContent += ")"; keb_inf.textContent += ")";
maininfos.appendChild(keb_inf); temptag.appendChild(keb_inf);
}
temptag.appendChild(maininfos);
}
temptag.appendChild(document.createTextNode(" 《"));
let e_readings = document.createElement("span");
e_readings.className = "nazeka_readings";
for(let j = 0; j < readings.length; j++)
{
e_readings.appendChild(document.createTextNode(readings[j].reb));
if(readings[j].inf)
{
for(let info of readings[j].inf)
{
let reb_inf = document.createElement("span");
reb_inf.className = "nazeka_reb_inf";
reb_inf.textContent += "(";
reb_inf.textContent += clip(info);
reb_inf.textContent += ")";
e_readings.appendChild(reb_inf);
}
}
if(j+1 != readings.length)
e_readings.appendChild(document.createTextNode("・"));
}
temptag.appendChild(e_readings);
temptag.appendChild(document.createTextNode("》"));
// list alternatives
let alternatives = [];
// don't list spellings if restricted to kana we didn't look up
for(let j = 0; j < term.k_ele.length; j++)
{
if(term.k_ele[j].keb != kanji_text)
{
let k = term.k_ele[j];
let invalid = !looked_up_kanji && k.restr;
if(!looked_up_kanji && k.restr)
{
for(let l = 0; l < k.restr.length; l++)
if(k.restr[l] == text)
invalid = false;
}
if(!looked_up_kanji && r_restr.indexOf(k.keb) < 0)
invalid = true;
if(!invalid)
alternatives.push(term.k_ele[j]);
} }
} }
if(j+1 < alternatives.length)
if(alternatives.length > 0) temptag.appendChild(document.createTextNode(", "));
temptag.appendChild(document.createTextNode(" (also "));
for(let j = 0; j < alternatives.length; j++)
{
temptag.appendChild(document.createTextNode(alternatives[j].keb));
if(alternatives[j].inf)
{
for(let info of alternatives[j].inf)
{
temptag.appendChild(document.createTextNode(" "));
let keb_inf = document.createElement("span");
keb_inf.className = "nazeka_keb_inf";
keb_inf.textContent += "(";
keb_inf.textContent += clip(info);
keb_inf.textContent += ")";
temptag.appendChild(keb_inf);
}
}
if(j+1 < alternatives.length)
temptag.appendChild(document.createTextNode(", "));
}
if(alternatives.length > 0)
temptag.appendChild(document.createTextNode(")"));
} }
if(alternatives.length > 0)
temptag.appendChild(document.createTextNode(")"));
} }
else else
found_kanji = false;
if(!found_kanji)
{ {
let main_reb = document.createElement("span"); let main_reb = document.createElement("span");
main_reb.className = "nazeka_main_reb"; main_reb.className = "nazeka_main_reb";
@@ -587,36 +508,8 @@ function build_div_inner (text, result)
container.appendChild(temptag); container.appendChild(temptag);
container.appendChild(document.createElement("br")); container.appendChild(document.createElement("br"));
let goodsenses = []; let goodsenses = term.sense;
for(let j = 0; j < term.sense.length; j++)
{
let sense = term.sense[j];
// FIXME: this shows too many senses. it's better than the previous code, which could show too few when looking up kana,
// but for looking up さくや for example, it shows both definitions, even though さくや is restricted to a spelling that is restricted to only one definition.
if(original_kana != "")
{
if(sense.stagr)
{
let found = false;
for(let l = 0; l < sense.stagr.length; l++)
if(sense.stagr[l] == original_kana)
found = true;
if(!found)
continue;
}
}
else if(sense.stagk && found_kanji)
{
let found = false;
for(let l = 0; l < sense.stagk.length; l++)
if(sense.stagk[l] == text)
found = true;
if(!found)
continue;
}
goodsenses.push(sense);
}
let lastpos = []; let lastpos = [];
let definition = document.createElement("div"); let definition = document.createElement("div");
definition.className = "nazeka_definitions"; definition.className = "nazeka_definitions";
@@ -716,6 +609,7 @@ function build_div_inner (text, result)
return temp; return temp;
} }
// this are the divs we use to contain the list of lookups. they're all contained in the same inner div from here.
function build_div_intermediary() function build_div_intermediary()
{ {
let middle = document.createElement("div"); let middle = document.createElement("div");
@@ -725,6 +619,7 @@ function build_div_intermediary()
return middle; return middle;
} }
// for popups with single lookup results
function build_div (text, result) function build_div (text, result)
{ {
last_displayed = [{text:text, result:result}]; last_displayed = [{text:text, result:result}];
@@ -732,6 +627,7 @@ function build_div (text, result)
middle.firstChild.appendChild(build_div_inner(text, result)); middle.firstChild.appendChild(build_div_inner(text, result));
return middle; return middle;
} }
// for popups with multiple lookup results
function build_div_compound (results) function build_div_compound (results)
{ {
last_displayed = results; last_displayed = results;