diff options
-rw-r--r-- | yomichan-user/conf.d/lib.js | 44 | ||||
-rw-r--r-- | yomichan-user/conf.d/sentence-export.js | 38 | ||||
-rw-r--r-- | yomichan-user/conf.d/word-export.css | 2 | ||||
-rw-r--r-- | yomichan-user/conf.d/word-export.css.m4 | 2 | ||||
-rw-r--r-- | yomichan-user/conf.d/word-export.js | 68 | ||||
-rw-r--r-- | yomichan-user/copy-bitmap.svg | 50 | ||||
-rw-r--r-- | yomichan-user/makefile | 7 |
7 files changed, 175 insertions, 36 deletions
diff --git a/yomichan-user/conf.d/lib.js b/yomichan-user/conf.d/lib.js new file mode 100644 index 0000000..6cb231e --- /dev/null +++ b/yomichan-user/conf.d/lib.js @@ -0,0 +1,44 @@ +async function getClipboardSettings() { + return (await yomichan.api.getSettings([{ + scope: "profile", + optionsContext: { current: true }, + path: 'clipboard' + }]))[0].result; +} + +async function setClipboardSettings(settings) { + await yomichan.api.modifySettings([{ + scope: "profile", + optionsContext: { current: true }, + path: 'clipboard', + action: 'set', + value: settings + }]); +} + +async function escapeYomichanCopy(text) { + var userClipboardSettings = await getClipboardSettings(); + var tempSettings = { + enableBackgroundMonitor: false, + enableSearchPageMonitor: false, + autoSearchContent: false, + maximumSearchLength: userClipboardSettings.maximumSearchLength, + }; + await setClipboardSettings(tempSettings); + + navigator.clipboard.writeText(text); + + // execute on next JS event loop + setTimeout(async () => await setClipboardSettings(userClipboardSettings), 0); +} + +function rubyHelper(element, reading) { + var out = ""; + for (var child of element.childNodes) { + if (reading && child.nodeName != "RT") continue; + if (!reading && child.nodeName == "RT") continue; + out += child.innerText; + } + return out; +} + diff --git a/yomichan-user/conf.d/sentence-export.js b/yomichan-user/conf.d/sentence-export.js index f15d890..176cdcd 100644 --- a/yomichan-user/conf.d/sentence-export.js +++ b/yomichan-user/conf.d/sentence-export.js @@ -1,21 +1,3 @@ -async function getClipboardSettings() { - return (await yomichan.api.getSettings([{ - scope: "profile", - optionsContext: { current: true }, - path: 'clipboard' - }]))[0].result; -} - -async function setClipboardSettings(settings) { - await yomichan.api.modifySettings([{ - scope: "profile", - optionsContext: { current: true }, - path: 'clipboard', - action: 'set', - value: settings - }]); -} - async function exportSentence() { var inputHTML = document.getElementById("query-parser-content"); var output = ""; @@ -42,19 +24,7 @@ async function exportSentence() { } } - var userClipboardSettings = await getClipboardSettings(); - var tempSettings = { - enableBackgroundMonitor: false, - enableSearchPageMonitor: false, - autoSearchContent: false, - maximumSearchLength: userClipboardSettings.maximumSearchLength, - }; - await setClipboardSettings(tempSettings); - - navigator.clipboard.writeText(output); - - // execute on next JS event loop - setTimeout(async () => await setClipboardSettings(userClipboardSettings), 0); + escapeYomichanCopy(output); return output; } @@ -72,13 +42,11 @@ function patchSearchBar() { searchBarOuter.insertBefore(button, searchBarOuter.childNodes[2]); } -function run() { +(() => { if (document.body.classList.contains("patched")) return; patchSearchBar(); document.body.classList.add("patched"); -} - -run(); +})(); diff --git a/yomichan-user/conf.d/word-export.css b/yomichan-user/conf.d/word-export.css new file mode 100644 index 0000000..0ae2eea --- /dev/null +++ b/yomichan-user/conf.d/word-export.css @@ -0,0 +1,2 @@ +.icon[data-icon=copy-bmp] { --icon-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzFfMjE4KSI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMV8xXzIxOCkiPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTEyIDRIN1Y3VjE1SDEySDE1VjdIMTJWNFpNMTMgNUgxNFY2SDEzVjVaIiBmaWxsPSJ1cmwoI3BhaW50MF9saW5lYXJfMV8yMTgpIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNyAzSDEySDEzVjRIMTRWNUgxNVY2SDE2VjdWMTVWMTZIMTVMNyAxNkg2VjE1VjRWM0g3Wk03IDE1VjRIMTJWNlY3SDEzSDE1VjE1SDdaTTE0IDVIMTNMMTMgNkgxNFY1WiIgZmlsbD0iYmxhY2siLz4KPC9nPgo8ZyBvcGFjaXR5PSIwLjUiIGNsaXAtcGF0aD0idXJsKCNjbGlwMl8xXzIxOCkiPgo8cGF0aCBkPSJNMyAxVjExSDJWMTNIMVYxNUg5VjE0SDExVjEzSDEyVjEySDEzVjVIMTJWNEgxMVYzSDEwVjJIOVYxSDNaIiBmaWxsPSJibGFjayIvPgo8L2c+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwM18xXzIxOCkiPgo8cGF0aCBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTcgMUgzVjVIMlYxMUgxVjEzSDNINEg3VjExSDExVjVIN1YxWk05IDJIOFYzVjRIOUgxMFYzSDlWMloiIGZpbGw9InVybCgjcGFpbnQxX2xpbmVhcl8xXzIxOCkiLz4KPHBhdGggZD0iTTEwIDEwSDZWMTNIMTBWMTBaIiBmaWxsPSJ1cmwoI3BhaW50Ml9saW5lYXJfMV8yMTgpIi8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNyAwSDNIMlYxVjEwSDNWMUg3VjRWNUg4SDExVjEwSDEwVjEySDExVjExSDEyVjVWNEgxMVYzSDEwVjRIOEw4IDJIOVYxSDhWMEg3Wk05IDJIMTBWM0g5VjJaTTggMTNWMTJIMTBWMTNIOFpNOCAxM1YxNEg0VjEzSDhaTTEgMTJIMlYxMEgxVjEyWk0xIDEySDBWMTRIMVYxMloiIGZpbGw9InVybCgjcGFpbnQzX2xpbmVhcl8xXzIxOCkiLz4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik03IDlIOFYxMEg3VjExVjEySDZWMTNINVYxNEgxVjEzSDRWMTJINVYxMUg2VjEwVjlIN1pNOCAxMEgxMFYxMUg4VjEwWiIgZmlsbD0iIzA2MDcwQSIvPgo8cmVjdCB4PSI0IiB5PSIyIiB3aWR0aD0iMyIgaGVpZ2h0PSIxIiBmaWxsPSIjMDYwNzBBIi8+CjxyZWN0IHg9IjQiIHk9IjQiIHdpZHRoPSIzIiBoZWlnaHQ9IjEiIGZpbGw9IiMwNjA3MEEiLz4KPHJlY3QgeD0iNCIgeT0iNiIgd2lkdGg9IjUiIGhlaWdodD0iMSIgZmlsbD0iIzA2MDcwQSIvPgo8L2c+CjwvZz4KPGRlZnM+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl8xXzIxOCIgeDE9IjExIiB5MT0iNCIgeDI9IjExIiB5Mj0iMTUiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iIzdCODE4RCIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiM0ODRBNTgiLz4KPC9saW5lYXJHcmFkaWVudD4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDFfbGluZWFyXzFfMjE4IiB4MT0iNiIgeTE9IjEiIHgyPSI2IiB5Mj0iMTMiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIj4KPHN0b3Agc3RvcC1jb2xvcj0iI0NDRDFGOSIvPgo8c3RvcCBvZmZzZXQ9IjEiIHN0b3AtY29sb3I9IiNCMkI0QkUiLz4KPC9saW5lYXJHcmFkaWVudD4KPGxpbmVhckdyYWRpZW50IGlkPSJwYWludDJfbGluZWFyXzFfMjE4IiB4MT0iOCIgeTE9IjEwIiB4Mj0iOCIgeTI9IjEzIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiM3QTgwOEMiLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNEE0QzVBIi8+CjwvbGluZWFyR3JhZGllbnQ+CjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQzX2xpbmVhcl8xXzIxOCIgeDE9IjYiIHkxPSIwIiB4Mj0iNiIgeTI9IjE0IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+CjxzdG9wIHN0b3AtY29sb3I9IiM5ODlDQjciLz4KPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNUM1QzVDIi8+CjwvbGluZWFyR3JhZGllbnQ+CjxjbGlwUGF0aCBpZD0iY2xpcDBfMV8yMTgiPgo8cmVjdCB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjxjbGlwUGF0aCBpZD0iY2xpcDFfMV8yMTgiPgo8cmVjdCB3aWR0aD0iMTAiIGhlaWdodD0iMTMiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2IDMpIi8+CjwvY2xpcFBhdGg+CjxjbGlwUGF0aCBpZD0iY2xpcDJfMV8yMTgiPgo8cmVjdCB3aWR0aD0iMTIiIGhlaWdodD0iMTQiIGZpbGw9IndoaXRlIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxIDEpIi8+CjwvY2xpcFBhdGg+CjxjbGlwUGF0aCBpZD0iY2xpcDNfMV8yMTgiPgo8cmVjdCB3aWR0aD0iMTIiIGhlaWdodD0iMTQiIGZpbGw9IndoaXRlIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==); } +button.action-button[hidden] { display: none; } diff --git a/yomichan-user/conf.d/word-export.css.m4 b/yomichan-user/conf.d/word-export.css.m4 new file mode 100644 index 0000000..b4bd026 --- /dev/null +++ b/yomichan-user/conf.d/word-export.css.m4 @@ -0,0 +1,2 @@ +.icon[data-icon=copy-bmp] { --icon-image: url`(data:image/svg+xml;base64,'undivert(copy-bitmap.svg.b64)`)'; } +button.action-button[hidden] { display: none; } diff --git a/yomichan-user/conf.d/word-export.js b/yomichan-user/conf.d/word-export.js new file mode 100644 index 0000000..fce1b48 --- /dev/null +++ b/yomichan-user/conf.d/word-export.js @@ -0,0 +1,68 @@ +function exportWord() { + var entry = this.parentNode.parentNode.parentNode; + var wordElement = entry.getElementsByClassName("headword-term")[0]; + var hasKanji = false; + + function addWord(reading) { + var out = ""; + for (var child of wordElement.childNodes) { + if (child.nodeName == "#text") out += child.textContent; + if (child.nodeName == "RUBY") { + hasKanji = true; + if (reading && out.length != 0) out += "\u30fb"; + out += rubyHelper(child, reading); + } + } + return out; + } + var kanji = addWord(false); + var reading = addWord(true) + var result = `${kanji}` + if (hasKanji) result += `\u3010${reading}\u3011`; + else result += " "; + + var tags = []; + + var pitchAccent = ""; + for (var tag of entry.getElementsByClassName("pronunciation-downstep-notation-number")) { + pitchAccent = tag.innerText.trim() + break; + } + if (pitchAccent) tags.push(`[${pitchAccent}]`); + + var usuallyKana = false; + for (var tag of entry.getElementsByClassName("tag-label-content")) + if (tag.innerText.trim() == "uk") + usuallyKana = true; + if (usuallyKana) tags.push("(uk)"); + + result += tags.join(" "); + + escapeYomichanCopy(result); +} + +function addWordCopyButtons() { + var definitions = document.getElementById("dictionary-entries").getElementsByClassName("entry"); + for (var definition of definitions) { + var actions = definition.getElementsByClassName("actions")[0]; + + var button = document.createElement("button"); + button.classList.add("action-button"); + button.onclick = exportWord; + var icon = document.createElement("span"); + icon.classList.add("icon"); + icon.classList.add("color-icon"); + icon.classList.add("action-icon"); + icon.setAttribute("data-icon", "copy-bmp"); + button.appendChild(icon); + actions.insertBefore(button, actions.childNodes[0]); + } +} + +(() => { + window.addEventListener("message", ev => { + // gets fired on search results render complete + if (ev.data.action == "renderMulti.response") + addWordCopyButtons(); + }); +})(); diff --git a/yomichan-user/copy-bitmap.svg b/yomichan-user/copy-bitmap.svg new file mode 100644 index 0000000..f2b157b --- /dev/null +++ b/yomichan-user/copy-bitmap.svg @@ -0,0 +1,50 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_1_218)"> +<g clip-path="url(#clip1_1_218)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M12 4H7V7V15H12H15V7H12V4ZM13 5H14V6H13V5Z" fill="url(#paint0_linear_1_218)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M7 3H12H13V4H14V5H15V6H16V7V15V16H15L7 16H6V15V4V3H7ZM7 15V4H12V6V7H13H15V15H7ZM14 5H13L13 6H14V5Z" fill="black"/> +</g> +<g opacity="0.5" clip-path="url(#clip2_1_218)"> +<path d="M3 1V11H2V13H1V15H9V14H11V13H12V12H13V5H12V4H11V3H10V2H9V1H3Z" fill="black"/> +</g> +<g clip-path="url(#clip3_1_218)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M7 1H3V5H2V11H1V13H3H4H7V11H11V5H7V1ZM9 2H8V3V4H9H10V3H9V2Z" fill="url(#paint1_linear_1_218)"/> +<path d="M10 10H6V13H10V10Z" fill="url(#paint2_linear_1_218)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M7 0H3H2V1V10H3V1H7V4V5H8H11V10H10V12H11V11H12V5V4H11V3H10V4H8L8 2H9V1H8V0H7ZM9 2H10V3H9V2ZM8 13V12H10V13H8ZM8 13V14H4V13H8ZM1 12H2V10H1V12ZM1 12H0V14H1V12Z" fill="url(#paint3_linear_1_218)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M7 9H8V10H7V11V12H6V13H5V14H1V13H4V12H5V11H6V10V9H7ZM8 10H10V11H8V10Z" fill="#06070A"/> +<rect x="4" y="2" width="3" height="1" fill="#06070A"/> +<rect x="4" y="4" width="3" height="1" fill="#06070A"/> +<rect x="4" y="6" width="5" height="1" fill="#06070A"/> +</g> +</g> +<defs> +<linearGradient id="paint0_linear_1_218" x1="11" y1="4" x2="11" y2="15" gradientUnits="userSpaceOnUse"> +<stop stop-color="#7B818D"/> +<stop offset="1" stop-color="#484A58"/> +</linearGradient> +<linearGradient id="paint1_linear_1_218" x1="6" y1="1" x2="6" y2="13" gradientUnits="userSpaceOnUse"> +<stop stop-color="#CCD1F9"/> +<stop offset="1" stop-color="#B2B4BE"/> +</linearGradient> +<linearGradient id="paint2_linear_1_218" x1="8" y1="10" x2="8" y2="13" gradientUnits="userSpaceOnUse"> +<stop stop-color="#7A808C"/> +<stop offset="1" stop-color="#4A4C5A"/> +</linearGradient> +<linearGradient id="paint3_linear_1_218" x1="6" y1="0" x2="6" y2="14" gradientUnits="userSpaceOnUse"> +<stop stop-color="#989CB7"/> +<stop offset="1" stop-color="#5C5C5C"/> +</linearGradient> +<clipPath id="clip0_1_218"> +<rect width="16" height="16" fill="white"/> +</clipPath> +<clipPath id="clip1_1_218"> +<rect width="10" height="13" fill="white" transform="translate(6 3)"/> +</clipPath> +<clipPath id="clip2_1_218"> +<rect width="12" height="14" fill="white" transform="translate(1 1)"/> +</clipPath> +<clipPath id="clip3_1_218"> +<rect width="12" height="14" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/yomichan-user/makefile b/yomichan-user/makefile index b965974..4e93d1a 100644 --- a/yomichan-user/makefile +++ b/yomichan-user/makefile @@ -2,18 +2,23 @@ all: yomichan-user.js yomichan-user.css +user.js: conf.d/lib.js user.js: conf.d/sentence-export.js user.css: conf.d/sentence-export.css - user.css: conf.d/custom.css +user.js: conf.d/word-export.js +user.css: conf.d/word-export.css include ../common.mk copy.svg.b64: copy.svg +copy-bitmap.svg.b64: copy-bitmap.svg conf.d/sentence-export.css: copy.svg.b64 conf.d/sentence-export.css: conf.d/sentence-export.css.m4 +conf.d/word-export.css: copy-bitmap.svg.b64 + user.js: cat $^ > $@ |