diff --git a/.eslintrc.json b/.eslintrc.json index 29a86ef1a..98c1fe5b0 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -562,6 +562,7 @@ "ext/js/core/extension-error.js", "ext/js/core/json.js", "ext/js/data/anki-note-data-creator.js", + "ext/js/data/array-buffer-util.js", "ext/js/dictionary/dictionary-data-util.js", "ext/js/display/display-content-manager.js", "ext/js/display/pronunciation-generator.js", diff --git a/ext/css/display.css b/ext/css/display.css index c44c3f26b..91a306bce 100644 --- a/ext/css/display.css +++ b/ext/css/display.css @@ -832,7 +832,6 @@ button.action-button:active { .entry { padding: var(--entry-vertical-padding) var(--entry-horizontal-padding); position: relative; - content-visibility: auto; contain-intrinsic-height: auto 500px; } .entry+.entry { diff --git a/ext/css/structured-content.css b/ext/css/structured-content.css index a2af2280e..020c7362e 100644 --- a/ext/css/structured-content.css +++ b/ext/css/structured-content.css @@ -41,8 +41,6 @@ } .gloss-image-link:hover { color: var(--accent-color-dark); -} -.gloss-image-link[href]:hover { cursor: pointer; } .gloss-image-container-overlay { diff --git a/ext/data/structured-content-style.json b/ext/data/structured-content-style.json index be30dc496..f3bfcf5a6 100644 --- a/ext/data/structured-content-style.json +++ b/ext/data/structured-content-style.json @@ -24,12 +24,6 @@ ["color", "inherit"] ] }, - { - "selectors": [".gloss-image-link[href]:hover"], - "styles": [ - ["cursor", "pointer"] - ] - }, { "selectors": [".gloss-image-container-overlay"], "styles": [ diff --git a/ext/js/display/display-content-manager.js b/ext/js/display/display-content-manager.js index 09693f6ff..ef3a146f2 100644 --- a/ext/js/display/display-content-manager.js +++ b/ext/js/display/display-content-manager.js @@ -17,6 +17,7 @@ */ import {EventListenerCollection} from '../core/event-listener-collection.js'; +import {base64ToArrayBuffer} from '../data/array-buffer-util.js'; /** * The content manager which is used when generating HTML display content. @@ -86,6 +87,19 @@ export class DisplayContentManager { this._loadMediaRequests = []; } + /** + * @param {string} path + * @param {string} dictionary + * @param {Window} window + */ + async openMediaInTab(path, dictionary, window) { + const data = await this._display.application.api.getMedia([{path, dictionary}]); + const buffer = base64ToArrayBuffer(data[0].content); + const blob = new Blob([buffer], {type: data[0].mediaType}); + const blobUrl = URL.createObjectURL(blob); + window.open(blobUrl, '_blank')?.focus(); + } + /** * @param {MouseEvent} e */ diff --git a/ext/js/display/structured-content-generator.js b/ext/js/display/structured-content-generator.js index 29a3c2e96..fe926cf30 100644 --- a/ext/js/display/structured-content-generator.js +++ b/ext/js/display/structured-content-generator.js @@ -107,6 +107,18 @@ export class StructuredContentGenerator { const overlay = this._createElement('span', 'gloss-image-container-overlay'); imageContainer.appendChild(overlay); + const linkText = this._createElement('span', 'gloss-image-link-text'); + linkText.textContent = 'Image'; + node.appendChild(linkText); + + if (this._contentManager instanceof DisplayContentManager) { + node.addEventListener('click', () => { + if (this._contentManager instanceof DisplayContentManager) { + void this._contentManager.openMediaInTab(path, dictionary, window); + } + }); + } + node.dataset.path = path; node.dataset.dictionary = dictionary; node.dataset.imageLoadState = 'not-loaded'; diff --git a/test/data/anki-note-builder-test-results.json b/test/data/anki-note-builder-test-results.json index 8b1a1d0be..13b6ed33a 100644 --- a/test/data/anki-note-builder-test-results.json +++ b/test/data/anki-note-builder-test-results.json @@ -863,12 +863,12 @@ "frequency-average-occurrence": "0", "furigana": "画像がぞう", "furigana-plain": "画像[がぞう]", - "glossary": "
(n, termsDictAlias)
", - "glossary-brief": "
", - "glossary-no-dictionary": "
(n)
", - "glossary-first": "
(n, termsDictAlias)
", - "glossary-first-brief": "
", - "glossary-first-no-dictionary": "
(n)
", + "glossary": "
(n, termsDictAlias)
", + "glossary-brief": "
", + "glossary-no-dictionary": "
(n)
", + "glossary-first": "
(n, termsDictAlias)
", + "glossary-first-brief": "
", + "glossary-first-no-dictionary": "
(n)
", "part-of-speech": "Noun", "pitch-accents": "", "pitch-accent-graphs": "", @@ -1570,12 +1570,12 @@ "frequency-average-occurrence": "0", "furigana": "画像がぞう", "furigana-plain": "画像[がぞう]", - "glossary": "
(n, termsDictAlias)
", - "glossary-brief": "
", - "glossary-no-dictionary": "
(n)
", - "glossary-first": "
(n, termsDictAlias)
", - "glossary-first-brief": "
", - "glossary-first-no-dictionary": "
(n)
", + "glossary": "
(n, termsDictAlias)
", + "glossary-brief": "
", + "glossary-no-dictionary": "
(n)
", + "glossary-first": "
(n, termsDictAlias)
", + "glossary-first-brief": "
", + "glossary-first-no-dictionary": "
(n)
", "part-of-speech": "Noun", "pitch-accents": "", "pitch-accent-graphs": "",