diff options
-rw-r--r-- | ext/bg/lang/deinflect.json | 818 | ||||
-rw-r--r-- | ext/fg/js/document.js | 114 | ||||
-rw-r--r-- | ext/fg/js/frontend.js | 6 | ||||
-rw-r--r-- | ext/fg/js/source.js | 15 | ||||
-rw-r--r-- | ext/mixed/js/display.js | 20 |
5 files changed, 914 insertions, 59 deletions
diff --git a/ext/bg/lang/deinflect.json b/ext/bg/lang/deinflect.json index 7ee00b2f..7a68ea71 100644 --- a/ext/bg/lang/deinflect.json +++ b/ext/bg/lang/deinflect.json @@ -784,6 +784,150 @@ "rulesOut": [ "adj-i" ] + }, + { + "kanaIn": "のたもうたら", + "kanaOut": "のたまう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いったら", + "kanaOut": "いく", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "おうたら", + "kanaOut": "おう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "こうたら", + "kanaOut": "こう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "そうたら", + "kanaOut": "そう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "とうたら", + "kanaOut": "とう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "行ったら", + "kanaOut": "行く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "逝ったら", + "kanaOut": "逝く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "往ったら", + "kanaOut": "往く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "請うたら", + "kanaOut": "請う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "乞うたら", + "kanaOut": "乞う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "恋うたら", + "kanaOut": "恋う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "問うたら", + "kanaOut": "問う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "負うたら", + "kanaOut": "負う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "沿うたら", + "kanaOut": "沿う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "添うたら", + "kanaOut": "添う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "副うたら", + "kanaOut": "副う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "厭うたら", + "kanaOut": "厭う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] } ], "-tari": [ @@ -891,6 +1035,150 @@ "rulesOut": [ "adj-i" ] + }, + { + "kanaIn": "のたもうたり", + "kanaOut": "のたまう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いったり", + "kanaOut": "いく", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "おうたり", + "kanaOut": "おう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "こうたり", + "kanaOut": "こう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "そうたり", + "kanaOut": "そう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "とうたり", + "kanaOut": "とう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "行ったり", + "kanaOut": "行く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "逝ったり", + "kanaOut": "逝く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "往ったり", + "kanaOut": "往く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "請うたり", + "kanaOut": "請う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "乞うたり", + "kanaOut": "乞う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "恋うたり", + "kanaOut": "恋う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "問うたり", + "kanaOut": "問う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "負うたり", + "kanaOut": "負う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "沿うたり", + "kanaOut": "沿う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "添うたり", + "kanaOut": "添う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "副うたり", + "kanaOut": "副う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "厭うたり", + "kanaOut": "厭う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] } ], "-te": [ @@ -998,6 +1286,150 @@ "rulesOut": [ "v5" ] + }, + { + "kanaIn": "のたもうて", + "kanaOut": "のたまう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いって", + "kanaOut": "いく", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "おうて", + "kanaOut": "おう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "こうて", + "kanaOut": "こう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "そうて", + "kanaOut": "そう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "とうて", + "kanaOut": "とう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "行って", + "kanaOut": "行く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "逝って", + "kanaOut": "逝く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "往って", + "kanaOut": "往く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "請うて", + "kanaOut": "請う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "乞うて", + "kanaOut": "乞う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "恋うて", + "kanaOut": "恋う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "問うて", + "kanaOut": "問う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "負うて", + "kanaOut": "負う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "沿うて", + "kanaOut": "沿う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "添うて", + "kanaOut": "添う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "副うて", + "kanaOut": "副う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "厭うて", + "kanaOut": "厭う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] } ], "-zu": [ @@ -1251,6 +1683,16 @@ ] }, { + "kanaIn": "させる", + "kanaOut": "す", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { "kanaIn": "たせる", "kanaOut": "つ", "rulesIn": [ @@ -1498,6 +1940,14 @@ ] }, { + "kanaIn": "き", + "kanaOut": "くる", + "rulesIn": [], + "rulesOut": [ + "vk" + ] + }, + { "kanaIn": "ぎ", "kanaOut": "ぎる", "rulesIn": [], @@ -1881,6 +2331,16 @@ ] }, { + "kanaIn": "される", + "kanaOut": "す", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { "kanaIn": "たれる", "kanaOut": "つ", "rulesIn": [ @@ -1929,12 +2389,10 @@ "rulesOut": [ "v5" ] - } - ], - "passive or causative": [ + }, { - "kanaIn": "される", - "kanaOut": "す", + "kanaIn": "られる", + "kanaOut": "る", "rulesIn": [ "v1" ], @@ -2048,6 +2506,150 @@ "rulesOut": [ "adj-i" ] + }, + { + "kanaIn": "のたもうた", + "kanaOut": "のたまう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いった", + "kanaOut": "いく", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "おうた", + "kanaOut": "おう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "こうた", + "kanaOut": "こう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "そうた", + "kanaOut": "そう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "とうた", + "kanaOut": "とう", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "行った", + "kanaOut": "行く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "逝った", + "kanaOut": "逝く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "往った", + "kanaOut": "往く", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "請うた", + "kanaOut": "請う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "乞うた", + "kanaOut": "乞う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "恋うた", + "kanaOut": "恋う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "問うた", + "kanaOut": "問う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "負うた", + "kanaOut": "負う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "沿うた", + "kanaOut": "沿う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "添うた", + "kanaOut": "添う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "副うた", + "kanaOut": "副う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "厭うた", + "kanaOut": "厭う", + "rulesIn": [], + "rulesOut": [ + "v5" + ] } ], "polite": [ @@ -2674,7 +3276,6 @@ ], "rulesOut": [ "v1", - "v5", "vk" ] }, @@ -2787,5 +3388,210 @@ "vs" ] } + ], + "causative passive": [ + { + "kanaIn": "かされる", + "kanaOut": "く", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "がされる", + "kanaOut": "ぐ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "たされる", + "kanaOut": "つ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "なされる", + "kanaOut": "ぬ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "ばされる", + "kanaOut": "ぶ", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "まされる", + "kanaOut": "む", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "らされる", + "kanaOut": "る", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "わされる", + "kanaOut": "う", + "rulesIn": [ + "v1" + ], + "rulesOut": [ + "v5" + ] + } + ], + "-toku": [ + { + "kanaIn": "いとく", + "kanaOut": "く", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "いどく", + "kanaOut": "ぐ", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "きとく", + "kanaOut": "くる", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "vk" + ] + }, + { + "kanaIn": "しとく", + "kanaOut": "す", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "しとく", + "kanaOut": "する", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "vs" + ] + }, + { + "kanaIn": "っとく", + "kanaOut": "う", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "っとく", + "kanaOut": "つ", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "っとく", + "kanaOut": "る", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んどく", + "kanaOut": "ぬ", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んどく", + "kanaOut": "ぶ", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "んどく", + "kanaOut": "む", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v5" + ] + }, + { + "kanaIn": "とく", + "kanaOut": "る", + "rulesIn": [ + "v5" + ], + "rulesOut": [ + "v1", + "vk" + ] + } ] } diff --git a/ext/fg/js/document.js b/ext/fg/js/document.js index 8a412f96..dc2a9b87 100644 --- a/ext/fg/js/document.js +++ b/ext/fg/js/document.js @@ -17,75 +17,107 @@ */ -function docOffsetCalc(element) { - const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; - const scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft; - - const clientTop = document.documentElement.clientTop || document.body.clientTop || 0; - const clientLeft = document.documentElement.clientLeft || document.body.clientLeft || 0; +function docSetImposterStyle(style, propertyName, value) { + style.setProperty(propertyName, value, 'important'); +} - const rect = element.getBoundingClientRect(); - const top = Math.round(rect.top + scrollTop - clientTop); - const left = Math.round(rect.left + scrollLeft - clientLeft); +function docImposterCreate(element, isTextarea) { + const elementStyle = window.getComputedStyle(element); + const elementRect = element.getBoundingClientRect(); + const documentRect = document.documentElement.getBoundingClientRect(); + const left = elementRect.left - documentRect.left; + const top = elementRect.top - documentRect.top; + + // Container + const container = document.createElement('div'); + const containerStyle = container.style; + docSetImposterStyle(containerStyle, 'all', 'initial'); + docSetImposterStyle(containerStyle, 'position', 'absolute'); + docSetImposterStyle(containerStyle, 'left', '0'); + docSetImposterStyle(containerStyle, 'top', '0'); + docSetImposterStyle(containerStyle, 'width', `${documentRect.width}px`); + docSetImposterStyle(containerStyle, 'height', `${documentRect.height}px`); + docSetImposterStyle(containerStyle, 'overflow', 'hidden'); + docSetImposterStyle(containerStyle, 'opacity', '0'); + + docSetImposterStyle(containerStyle, 'pointer-events', 'none'); + docSetImposterStyle(containerStyle, 'z-index', '2147483646'); + + // Imposter + const imposter = document.createElement('div'); + const imposterStyle = imposter.style; - return {top, left}; -} + imposter.innerText = element.value; -function docImposterCreate(element) { - const styleProps = window.getComputedStyle(element); - const stylePairs = []; - for (const key of styleProps) { - stylePairs.push(`${key}: ${styleProps[key]};`); + for (let i = 0, ii = elementStyle.length; i < ii; ++i) { + const property = elementStyle[i]; + docSetImposterStyle(imposterStyle, property, elementStyle.getPropertyValue(property)); + } + docSetImposterStyle(imposterStyle, 'position', 'absolute'); + docSetImposterStyle(imposterStyle, 'top', `${top}px`); + docSetImposterStyle(imposterStyle, 'left', `${left}px`); + docSetImposterStyle(imposterStyle, 'margin', '0'); + docSetImposterStyle(imposterStyle, 'pointer-events', 'auto'); + + if (isTextarea) { + if (elementStyle.overflow === 'visible') { + docSetImposterStyle(imposterStyle, 'overflow', 'auto'); + } + } else { + docSetImposterStyle(imposterStyle, 'overflow', 'hidden'); + docSetImposterStyle(imposterStyle, 'white-space', 'nowrap'); + docSetImposterStyle(imposterStyle, 'line-height', elementStyle.height); } - const offset = docOffsetCalc(element); - const imposter = document.createElement('div'); - imposter.className = 'yomichan-imposter'; - imposter.innerText = element.value; - imposter.style.cssText = stylePairs.join('\n'); - imposter.style.position = 'absolute'; - imposter.style.top = `${offset.top}px`; - imposter.style.left = `${offset.left}px`; - imposter.style.opacity = 0; - imposter.style.zIndex = 2147483646; - if (element.nodeName === 'TEXTAREA' && styleProps.overflow === 'visible') { - imposter.style.overflow = 'auto'; + container.appendChild(imposter); + document.body.appendChild(container); + + // Adjust size + const imposterRect = imposter.getBoundingClientRect(); + if (imposterRect.width !== elementRect.width || imposterRect.height !== elementRect.height) { + const width = parseFloat(elementStyle.width) + (elementRect.width - imposterRect.width); + const height = parseFloat(elementStyle.height) + (elementRect.height - imposterRect.height); + docSetImposterStyle(imposterStyle, 'width', `${width}px`); + docSetImposterStyle(imposterStyle, 'height', `${height}px`); } - document.body.appendChild(imposter); imposter.scrollTop = element.scrollTop; imposter.scrollLeft = element.scrollLeft; - return imposter; -} - -function docImposterDestroy() { - for (const element of document.getElementsByClassName('yomichan-imposter')) { - element.parentNode.removeChild(element); - } + return [imposter, container]; } function docRangeFromPoint(point) { const element = document.elementFromPoint(point.x, point.y); let imposter = null; + let imposterContainer = null; if (element) { switch (element.nodeName) { case 'IMG': case 'BUTTON': return new TextSourceElement(element); case 'INPUT': + [imposter, imposterContainer] = docImposterCreate(element, false); + break; case 'TEXTAREA': - imposter = docImposterCreate(element); + [imposter, imposterContainer] = docImposterCreate(element, true); break; } } const range = document.caretRangeFromPoint(point.x, point.y); - if (imposter !== null) { - imposter.style.zIndex = -2147483646; + if (range !== null && isPointInRange(point, range)) { + if (imposter !== null) { + docSetImposterStyle(imposterContainer.style, 'z-index', '-2147483646'); + docSetImposterStyle(imposter.style, 'pointer-events', 'none'); + } + return new TextSourceRange(range, '', imposterContainer); + } else { + if (imposterContainer !== null) { + imposterContainer.parentNode.removeChild(imposterContainer); + } + return null; } - - return range !== null && isPointInRange(point, range) ? new TextSourceRange(range) : null; } function docSentenceExtract(source, extent) { diff --git a/ext/fg/js/frontend.js b/ext/fg/js/frontend.js index 72379062..5a8d18c1 100644 --- a/ext/fg/js/frontend.js +++ b/ext/fg/js/frontend.js @@ -311,10 +311,11 @@ class Frontend { this.onError(e); } } finally { + if (textSource !== null) { + textSource.cleanup(); + } if (hideResults && this.options.scanning.autoHideResults) { this.searchClear(); - } else { - docImposterDestroy(); } this.pendingLookup = false; @@ -377,7 +378,6 @@ class Frontend { } searchClear() { - docImposterDestroy(); this.popup.hide(); this.popup.clearAutoPlayTimer(); diff --git a/ext/fg/js/source.js b/ext/fg/js/source.js index a5421934..e724488d 100644 --- a/ext/fg/js/source.js +++ b/ext/fg/js/source.js @@ -25,13 +25,20 @@ const IGNORE_TEXT_PATTERN = /\u200c/; */ class TextSourceRange { - constructor(range, content='') { + constructor(range, content, imposterContainer) { this.range = range; this.content = content; + this.imposterContainer = imposterContainer; } clone() { - return new TextSourceRange(this.range.cloneRange(), this.content); + return new TextSourceRange(this.range.cloneRange(), this.content, this.imposterContainer); + } + + cleanup() { + if (this.imposterContainer !== null && this.imposterContainer.parentNode !== null) { + this.imposterContainer.parentNode.removeChild(this.imposterContainer); + } } text() { @@ -242,6 +249,10 @@ class TextSourceElement { return new TextSourceElement(this.element, this.content); } + cleanup() { + // NOP + } + text() { return this.content; } diff --git a/ext/mixed/js/display.js b/ext/mixed/js/display.js index a2707bd0..4620e198 100644 --- a/ext/mixed/js/display.js +++ b/ext/mixed/js/display.js @@ -84,16 +84,22 @@ class Display { if (textSource === null) { return false; } - textSource.setEndOffset(this.options.scanning.length); - const {definitions, length} = await apiTermsFind(textSource.text()); - if (definitions.length === 0) { - return false; - } + let definitions, length, sentence; + try { + textSource.setEndOffset(this.options.scanning.length); - textSource.setEndOffset(length); + ({definitions, length} = await apiTermsFind(textSource.text())); + if (definitions.length === 0) { + return false; + } - const sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); + textSource.setEndOffset(length); + + sentence = docSentenceExtract(textSource, this.options.anki.sentenceExt); + } finally { + textSource.cleanup(); + } const context = { source: { |