diff options
author | Loek Le Blansch <loek@pipeframe.xyz> | 2024-07-03 14:08:21 +0200 |
---|---|---|
committer | Loek Le Blansch <loek@pipeframe.xyz> | 2024-07-03 14:08:21 +0200 |
commit | 0b905b2dd3d470301cef8bc22dfb2a323de826bb (patch) | |
tree | cdebe8d10f156e98dff64866970adbe421e48dbf /ext | |
parent | 066ca66fc4033da39d0aecd73b0f5c200cb3f3ed (diff) |
Diffstat (limited to 'ext')
-rw-r--r-- | ext/css/display.css | 2 | ||||
-rw-r--r-- | ext/css/material.css | 2 | ||||
-rw-r--r-- | ext/images/copy-bitmap.svg | 58 | ||||
-rw-r--r-- | ext/images/copy.svg | 3 | ||||
-rw-r--r-- | ext/js/display/search-display-controller.js | 35 | ||||
-rw-r--r-- | ext/js/refold-tools.js | 46 | ||||
-rw-r--r-- | ext/search.html | 1 | ||||
-rw-r--r-- | ext/templates-display.html | 3 |
8 files changed, 149 insertions, 1 deletions
diff --git a/ext/css/display.css b/ext/css/display.css index febcb62b..f04865a8 100644 --- a/ext/css/display.css +++ b/ext/css/display.css @@ -646,7 +646,7 @@ button.action-button { background-color var(--animation-duration) linear; } button.action-button[hidden] { - display: block; + display: none; visibility: hidden; opacity: 0; transition: diff --git a/ext/css/material.css b/ext/css/material.css index 00265586..d93b31d5 100644 --- a/ext/css/material.css +++ b/ext/css/material.css @@ -290,6 +290,8 @@ body { --icon-image: url(/images/material-right-arrow.svg); --icon-size: var(--material-arrow-dimension1) var(--material-arrow-dimension2); } +.icon[data-icon=copy] { --icon-image: url('/images/copy.svg'); } +.icon[data-icon=copy-bmp] { --icon-image: url('/images/copy-bitmap.svg'); } /* Checkbox */ diff --git a/ext/images/copy-bitmap.svg b/ext/images/copy-bitmap.svg new file mode 100644 index 00000000..79497640 --- /dev/null +++ b/ext/images/copy-bitmap.svg @@ -0,0 +1,58 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_201_3)"> +<g clip-path="url(#clip1_201_3)" filter="url(#filter0_d_201_3)"> +<path d="M6.5 3.5H12.5L15.5 6.5V15.5H6.5V3.5Z" fill="url(#paint0_linear_201_3)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M6 3H12.7071L16 6.29289V16H6V3ZM7 4V15H15V6.70711L12.2929 4H7Z" fill="black"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M8 6H11V7H8V6ZM8 8H14V9H8V8ZM8 10H14V11H8V10Z" fill="black"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M12 3.5L12.8536 3.14645L15.8536 6.14645L15.5 7H12.5L12 6.5V3.5ZM13 4.70711V6H14.2929L13 4.70711Z" fill="black"/> +</g> +<path fill-rule="evenodd" clip-rule="evenodd" d="M2.85392 1H12.8539V4.5C12.8539 6.4978 12.8024 7.83888 12.6435 8.78626C12.4811 9.75424 12.1984 10.3626 11.7075 10.8536C11.6778 10.8832 11.6316 10.9404 11.5687 11.0183C11.3326 11.3109 10.8609 11.8952 10.1445 12.4069C9.1901 13.0886 7.73097 13.739 5.40913 13.9969L5.38161 14H1.35392L1.00079 13.1475L1 13.1468L1.01029 13.1359C1.02072 13.1247 1.03796 13.1057 1.06105 13.0789C1.10723 13.0253 1.17678 12.9404 1.26205 12.8231C1.43258 12.5886 1.66602 12.225 1.90151 11.7246C2.37158 10.7257 2.85392 9.17316 2.85392 7V1Z" fill="black" fill-opacity="0.25"/> +<g clip-path="url(#clip2_201_3)"> +<path d="M11.5 0.5H2.5V6C2.5 10.5 0.5 12.5 0.5 12.5H4.5C9 12 10 10 10.5 9.5C11.2906 8.70943 11.5 7.5 11.5 3.5V0.5Z" fill="url(#paint1_linear_201_3)"/> +<path d="M4.5 12.5C8.33351 12.1185 9.74654 10.4854 10.5 9.5C9 9.5 7.5 9 6.5 8.5C6.5 12 0.5 12.5 0.5 12.5H4.5Z" fill="url(#paint2_linear_201_3)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M6 8.5L6.72361 8.05279C7.67681 8.52939 9.09948 9 10.5 9L10.8972 9.8037C10.5053 10.3163 9.92063 11.0251 8.92001 11.6505C7.91997 12.2755 6.53256 12.8002 4.54952 12.9975L4.52482 13H0.5L0.458634 12.0055C0.458302 12.0017 0.458263 12.0017 0.458263 12.0017L0.460536 12.0015L0.471039 12.0006L0.516263 11.9962C0.556817 11.992 0.617629 11.9853 0.695795 11.9755C0.852236 11.956 1.07756 11.9241 1.34866 11.8751C1.89298 11.7769 2.61165 11.6116 3.32444 11.3443C4.80265 10.79 6 9.9034 6 8.5ZM4.34223 12H4.47497C6.31186 11.814 7.55342 11.4112 8.40287 10.8803C8.85247 10.5993 9.19078 10.2217 9.4753 9.93176C8.54065 9.81058 7.65284 9.54194 6.91989 9.23958C6.61454 10.5992 5.48328 11.4618 4.34223 12Z" fill="black"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M2 0H12V3.5C12 5.4978 11.9485 6.83888 11.7896 7.78626C11.6272 8.75424 11.3445 9.36265 10.8536 9.85355C10.8239 9.88323 10.7777 9.94044 10.7148 10.0183C10.4786 10.3109 10.007 10.8952 9.29062 11.4069C8.33618 12.0886 6.87705 12.739 4.55521 12.9969L4.52769 13H0.499999L0.146867 12.1475C0.146125 12.1468 0.146103 12.1468 0.14608 12.1468L0.156367 12.1359C0.166803 12.1247 0.184044 12.1057 0.207132 12.0789C0.253314 12.0253 0.322855 11.9404 0.408131 11.8231C0.578663 11.5886 0.812099 11.225 1.04759 10.7246C1.51766 9.72571 2 8.17316 2 6V0ZM1.49282 12H4.47209C6.63375 11.756 7.91714 11.159 8.70938 10.5931C9.29476 10.175 9.58709 9.813 9.83125 9.51064C9.93869 9.37759 10.0368 9.25609 10.1464 9.14645C10.4461 8.84679 10.6634 8.45519 10.8034 7.62081C10.9468 6.76583 11 5.5022 11 3.5V1H3V6C3 8.32684 2.48234 10.0243 1.95241 11.1504C1.79547 11.4839 1.63781 11.7665 1.49282 12Z" fill="url(#paint3_linear_201_3)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M2 0H12V3.5C12 5.4978 11.9485 6.83888 11.7896 7.78626C11.6272 8.75424 11.3445 9.36265 10.8536 9.85355C10.8239 9.88323 10.7777 9.94044 10.7148 10.0183C10.4786 10.3109 10.007 10.8952 9.29062 11.4069C8.33618 12.0886 6.87705 12.739 4.55521 12.9969L4.52769 13H0.499999L0.146867 12.1475C0.146125 12.1468 0.146103 12.1468 0.14608 12.1468L0.156367 12.1359C0.166803 12.1247 0.184044 12.1057 0.207132 12.0789C0.253314 12.0253 0.322855 11.9404 0.408131 11.8231C0.578663 11.5886 0.812099 11.225 1.04759 10.7246C1.51766 9.72571 2 8.17316 2 6V0ZM1.49282 12H4.47209C6.63375 11.756 7.91714 11.159 8.70938 10.5931C9.29476 10.175 9.58709 9.813 9.83125 9.51064C9.93869 9.37759 10.0368 9.25609 10.1464 9.14645C10.4461 8.84679 10.6634 8.45519 10.8034 7.62081C10.9468 6.76583 11 5.5022 11 3.5V1H3V6C3 8.32684 2.48234 10.0243 1.95241 11.1504C1.79547 11.4839 1.63781 11.7665 1.49282 12Z" fill="url(#paint4_linear_201_3)"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M4 2H10V3H4V2ZM4 4H10V5H4V4ZM4 6H10V7H4V6Z" fill="black"/> +</g> +</g> +<defs> +<filter id="filter0_d_201_3" x="6" y="3" width="11" height="14" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dx="1" dy="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_201_3"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_201_3" result="shape"/> +</filter> +<linearGradient id="paint0_linear_201_3" x1="11" y1="3.5" x2="11" y2="15.5" gradientUnits="userSpaceOnUse"> +<stop stop-color="#7B818D"/> +<stop offset="1" stop-color="#484A58"/> +</linearGradient> +<linearGradient id="paint1_linear_201_3" x1="6" y1="0.5" x2="6" y2="12.5" gradientUnits="userSpaceOnUse"> +<stop stop-color="#CCD1F9"/> +<stop offset="1" stop-color="#B2B4BE"/> +</linearGradient> +<linearGradient id="paint2_linear_201_3" x1="5.5" y1="8.5" x2="5.5" y2="12.5" gradientUnits="userSpaceOnUse"> +<stop stop-color="#7A808C"/> +<stop offset="1" stop-color="#4A4C5A"/> +</linearGradient> +<linearGradient id="paint3_linear_201_3" x1="6.07304" y1="0" x2="6.07304" y2="13" gradientUnits="userSpaceOnUse"> +<stop stop-color="#989CB7"/> +<stop offset="1" stop-color="#5C5C5C"/> +</linearGradient> +<linearGradient id="paint4_linear_201_3" x1="6.07304" y1="0" x2="6.07304" y2="13" gradientUnits="userSpaceOnUse"> +<stop stop-color="#989CB7"/> +<stop offset="1" stop-color="#5C5C5C"/> +</linearGradient> +<clipPath id="clip0_201_3"> +<rect width="16" height="16" fill="white"/> +</clipPath> +<clipPath id="clip1_201_3"> +<rect width="10" height="13" fill="white" transform="translate(6 3)"/> +</clipPath> +<clipPath id="clip2_201_3"> +<rect width="12" height="13" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/ext/images/copy.svg b/ext/images/copy.svg new file mode 100644 index 00000000..ff2f5a9d --- /dev/null +++ b/ext/images/copy.svg @@ -0,0 +1,3 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M2 2C2 1.17157 2.67157 0.5 3.5 0.5H10.5V2L3.5 2V12H2V2ZM4.5 4.5C4.5 3.67157 5.17157 3 6 3H12.5C13.3284 3 14 3.67157 14 4.5V14.25C14 15.0784 13.3284 15.75 12.5 15.75H6C5.17157 15.75 4.5 15.0784 4.5 14.25V4.5ZM12.5 4.5H6V14.25H12.5V4.5Z" fill="currentColor"/> +</svg> diff --git a/ext/js/display/search-display-controller.js b/ext/js/display/search-display-controller.js index b1e26750..20adbc82 100644 --- a/ext/js/display/search-display-controller.js +++ b/ext/js/display/search-display-controller.js @@ -21,6 +21,7 @@ import {ClipboardMonitor} from '../comm/clipboard-monitor.js'; import {createApiMap, invokeApiMapHandler} from '../core/api-map.js'; import {EventListenerCollection} from '../core/event-listener-collection.js'; import {querySelectorNotNull} from '../dom/query-selector.js'; +import { escapeYomichanCopy } from '../refold-tools.js'; export class SearchDisplayController { /** @@ -36,6 +37,8 @@ export class SearchDisplayController { /** @type {import('./search-persistent-state-controller.js').SearchPersistentStateController} */ this._searchPersistentStateController = searchPersistentStateController; /** @type {HTMLButtonElement} */ + this._copySentenceButton = querySelectorNotNull(document, '#anki-sentence-export-button'); + /** @type {HTMLButtonElement} */ this._searchButton = querySelectorNotNull(document, '#search-button'); /** @type {HTMLButtonElement} */ this._searchBackButton = querySelectorNotNull(document, '#search-back-button'); @@ -101,6 +104,7 @@ export class SearchDisplayController { this._display.queryParserVisible = true; this._display.setHistorySettings({useBrowserHistory: true}); + this._copySentenceButton.addEventListener('click', this._onCopySentence.bind(this), false); this._searchButton.addEventListener('click', this._onSearch.bind(this), false); this._searchBackButton.addEventListener('click', this._onSearchBackButtonClick.bind(this), false); this._wanakanaEnableCheckbox.addEventListener('change', this._onWanakanaEnableChange.bind(this)); @@ -255,6 +259,37 @@ export class SearchDisplayController { this._search(true, 'new', true, null); } + /** @param {MouseEvent} e */ + _onCopySentence(e) { + e.preventDefault(); + var inputHTML = document.getElementById("query-parser-content"); + var output = ""; + + var selection = window.getSelection(); + // TODO: fix right-to-left selected text + + for (var child of inputHTML.children) { + for (var subchild of child.childNodes) { + if (subchild.nodeName == '#text') { + for (var i in subchild.textContent) { + if (selection.anchorNode == subchild && i == selection.anchorOffset) output += "*"; + output += subchild.textContent[i]; + if (selection.focusNode == subchild && i == selection.focusOffset - 1) output += "*"; + } + continue; + } + if (subchild.nodeName == 'RUBY') { + if (selection.anchorNode.parentNode.parentNode == subchild) output += "*"; + output += `[${subchild.childNodes[0].innerText}](${subchild.childNodes[1].innerText})`; + if (selection.focusNode.parentNode.parentNode == subchild) output += "*"; + continue; + } + } + } + + escapeYomichanCopy(output); + } + /** * @param {MouseEvent} e */ diff --git a/ext/js/refold-tools.js b/ext/js/refold-tools.js new file mode 100644 index 00000000..99fc114f --- /dev/null +++ b/ext/js/refold-tools.js @@ -0,0 +1,46 @@ +// TODO: how to get yomichan.api? + +export async function getClipboardSettings() { + return (await yomichan.api.getSettings([{ + scope: "profile", + optionsContext: { current: true }, + path: 'clipboard' + }]))[0].result; +} + +export async function setClipboardSettings(settings) { + await yomichan.api.modifySettings([{ + scope: "profile", + optionsContext: { current: true }, + path: 'clipboard', + action: 'set', + value: settings + }]); +} + +export 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); +} + +export 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.textContent; + } + return out; +} + diff --git a/ext/search.html b/ext/search.html index 4324dad5..e2c2f525 100644 --- a/ext/search.html +++ b/ext/search.html @@ -59,6 +59,7 @@ <div class="search-header"> <div class="search-textbox-container"> <textarea id="search-textbox" class="scrollbar" placeholder="Input a term, expression, sentence, or block of text" autocomplete="off" lang="ja" autofocus></textarea> + <button type="button" id="anki-sentence-export-button" class="search-button"><span class="icon" data-icon="copy"></span></button> <button type="button" id="search-back-button" class="search-button" hidden><span class="icon" data-icon="left-chevron"></span></button> <button type="button" id="search-button" class="search-button"><span class="icon" data-icon="magnifying-glass"></span></button> </div> diff --git a/ext/templates-display.html b/ext/templates-display.html index f52fb1fa..a96c7d50 100644 --- a/ext/templates-display.html +++ b/ext/templates-display.html @@ -5,6 +5,9 @@ <div class="entry-current-indicator" title="Current entry"><span class="entry-current-indicator-inner"></span></div> <div class="entry-header"> <div class="actions"> + <button type="button" class="action-button" title="Copy definition"> + <span class="action-icon icon color-icon" data-icon="copy-bmp"></span> + </button> <button type="button" class="action-button action-button-collapsible" data-action="view-tags" hidden disabled> <span class="action-icon icon" data-icon="tag"></span> </button> |