aboutsummaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2021-06-06 14:47:48 -0400
committertoasted-nutbread <toasted-nutbread@users.noreply.github.com>2021-06-10 19:03:57 -0400
commit5dbc79d046ed63444895cf8720165b95b9906735 (patch)
tree4411f7030701dac669b566b77b4e91342e040584 /ext
parent15ebb483d896916553ba5d729c22be4e545cc08a (diff)
Structured content updates (#1733)
* Add support for imageRendering * Make crisp-edges appearance on Firefox more similar to Chrome * Refactor * Add background option * Move data-image-rendering attribute * Restructure * Organize * Add support for appearance * Update test dictionary * Update tests
Diffstat (limited to 'ext')
-rw-r--r--ext/css/display.css37
-rw-r--r--ext/data/schemas/dictionary-term-bank-v3-schema.json34
-rw-r--r--ext/display-templates.html10
-rw-r--r--ext/js/display/display-generator.js38
-rw-r--r--ext/js/display/display.js4
-rw-r--r--ext/js/language/dictionary-importer.js17
6 files changed, 128 insertions, 12 deletions
diff --git a/ext/css/display.css b/ext/css/display.css
index ac9dae0a..45658f19 100644
--- a/ext/css/display.css
+++ b/ext/css/display.css
@@ -1566,6 +1566,8 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
line-height: 0;
font-size: calc(1em / var(--font-size-no-units));
overflow: hidden;
+}
+.gloss-image-link[data-background=true]>.gloss-image-container {
background-color: var(--gloss-image-background-color);
}
.gloss-image-link {
@@ -1600,6 +1602,18 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
text-align: center;
padding: 0.25em;
}
+.gloss-image-background {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ background-color: var(--text-color);
+
+ --image: none;
+ --icon-size: contain;
+ --icon-image: var(--image);
+}
.gloss-image {
display: inline-block;
vertical-align: top;
@@ -1617,13 +1631,27 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
.gloss-image:not([src]) {
display: none;
}
-.gloss-image[data-pixelated=true] {
+.gloss-image-link[data-image-rendering=pixelated] .gloss-image,
+.gloss-image-link[data-image-rendering=pixelated] .gloss-image-background {
image-rendering: auto;
image-rendering: -moz-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: pixelated;
image-rendering: crisp-edges;
}
+.gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,
+.gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background {
+ image-rendering: auto;
+ image-rendering: -moz-crisp-edges;
+ image-rendering: -webkit-optimize-contrast;
+ image-rendering: crisp-edges;
+}
+:root[data-browser=firefox] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,
+:root[data-browser=firefox] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background,
+:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image,
+:root[data-browser=firefox-mobile] .gloss-image-link[data-image-rendering=crisp-edges] .gloss-image-background {
+ image-rendering: auto;
+}
.gloss-image-link[data-has-aspect-ratio=true] .gloss-image-aspect-ratio-sizer {
display: inline-block;
width: 0;
@@ -1645,6 +1673,13 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
white-space: pre-line;
}
+.gloss-image-link[data-appearance=monochrome] .gloss-image {
+ visibility: hidden;
+}
+.gloss-image-link:not([data-appearance=monochrome]) .gloss-image-background {
+ display: none;
+}
+
.gloss-image-link[data-size-units=em] .gloss-image-container {
font-size: 1em;
}
diff --git a/ext/data/schemas/dictionary-term-bank-v3-schema.json b/ext/data/schemas/dictionary-term-bank-v3-schema.json
index 9003cbf3..fd3f3844 100644
--- a/ext/data/schemas/dictionary-term-bank-v3-schema.json
+++ b/ext/data/schemas/dictionary-term-bank-v3-schema.json
@@ -70,6 +70,23 @@
"description": "Whether or not the image should appear pixelated at sizes larger than the image's native resolution.",
"default": false
},
+ "imageRendering": {
+ "type": "string",
+ "description": "Controls how the image is rendered. The value of this field supersedes the pixelated field.",
+ "enum": ["auto", "pixelated", "crisp-edges"],
+ "default": "auto"
+ },
+ "appearance": {
+ "type": "string",
+ "description": "Controls the appearance of the image. The \"monochrome\" value will mask the opaque parts of the image using the current text color.",
+ "enum": ["auto", "monochrome"],
+ "default": "auto"
+ },
+ "background": {
+ "type": "boolean",
+ "description": "Whether or not a background color is displayed behind the image.",
+ "default": true
+ },
"collapsed": {
"type": "boolean",
"description": "Whether or not the image is collapsed by default.",
@@ -219,6 +236,23 @@
"description": "Whether or not the image should appear pixelated at sizes larger than the image's native resolution.",
"default": false
},
+ "imageRendering": {
+ "type": "string",
+ "description": "Controls how the image is rendered. The value of this field supersedes the pixelated field.",
+ "enum": ["auto", "pixelated", "crisp-edges"],
+ "default": "auto"
+ },
+ "appearance": {
+ "type": "string",
+ "description": "Controls the appearance of the image. The \"monochrome\" value will mask the opaque parts of the image using the current text color.",
+ "enum": ["auto", "monochrome"],
+ "default": "auto"
+ },
+ "background": {
+ "type": "boolean",
+ "description": "Whether or not a background color is displayed behind the image.",
+ "default": true
+ },
"collapsed": {
"type": "boolean",
"description": "Whether or not the image is collapsed by default.",
diff --git a/ext/display-templates.html b/ext/display-templates.html
index 61d55638..0ad02748 100644
--- a/ext/display-templates.html
+++ b/ext/display-templates.html
@@ -57,7 +57,15 @@
</li></template>
<template id="definition-disambiguation-template"><span class="definition-disambiguation"></span></template>
<template id="gloss-item-template"><li class="gloss-item click-scannable"><span class="gloss-separator"> </span><span class="gloss-content"></span></li></template>
-<template id="gloss-item-image-template"><a class="gloss-image-link" target="_blank" rel="noreferrer noopener"><span class="gloss-image-container"><span class="gloss-image-aspect-ratio-sizer"></span><img class="gloss-image" alt=""><span class="gloss-image-container-overlay"></span></span><span class="gloss-image-link-text">Image</span></a></template>
+<template id="gloss-item-image-template" data-remove-whitespace-text="true"><a class="gloss-image-link" target="_blank" rel="noreferrer noopener">
+ <span class="gloss-image-container">
+ <span class="gloss-image-aspect-ratio-sizer"></span>
+ <span class="gloss-image-background icon"></span>
+ <img class="gloss-image" alt="">
+ <span class="gloss-image-container-overlay"></span>
+ </span>
+ <span class="gloss-image-link-text">Image</span>
+</a></template>
<template id="gloss-item-image-description-template"> <span class="gloss-image-description"></span></template>
<template id="inflection-template"><span class="inflection"></span><span class="inflection-separator"> </span></template>
diff --git a/ext/js/display/display-generator.js b/ext/js/display/display-generator.js
index 484dc6a9..6a5b26f1 100644
--- a/ext/js/display/display-generator.js
+++ b/ext/js/display/display-generator.js
@@ -340,7 +340,22 @@ class DisplayGenerator {
}
_createDefinitionImage(data, dictionary) {
- const {path, width, height, preferredWidth, preferredHeight, title, pixelated, collapsed, collapsible, verticalAlign, sizeUnits} = data;
+ const {
+ path,
+ width,
+ height,
+ preferredWidth,
+ preferredHeight,
+ title,
+ pixelated,
+ imageRendering,
+ appearance,
+ background,
+ collapsed,
+ collapsible,
+ verticalAlign,
+ sizeUnits
+ } = data;
const hasPreferredWidth = (typeof preferredWidth === 'number');
const hasPreferredHeight = (typeof preferredHeight === 'number');
@@ -356,10 +371,18 @@ class DisplayGenerator {
);
const node = this._templates.instantiate('gloss-item-image');
+ const imageContainer = node.querySelector('.gloss-image-container');
+ const aspectRatioSizer = node.querySelector('.gloss-image-aspect-ratio-sizer');
+ const image = node.querySelector('.gloss-image');
+ const imageBackground = node.querySelector('.gloss-image-background');
+
node.dataset.path = path;
node.dataset.dictionary = dictionary;
node.dataset.imageLoadState = 'not-loaded';
node.dataset.hasAspectRatio = 'true';
+ node.dataset.imageRendering = typeof imageRendering === 'string' ? imageRendering : (pixelated ? 'pixelated' : 'auto');
+ node.dataset.appearance = typeof appearance === 'string' ? appearance : 'auto';
+ node.dataset.background = typeof background === 'boolean' ? `${background}` : 'true';
node.dataset.collapsed = typeof collapsed === 'boolean' ? `${collapsed}` : 'false';
node.dataset.collapsible = typeof collapsible === 'boolean' ? `${collapsible}` : 'true';
if (typeof verticalAlign === 'string') {
@@ -369,39 +392,36 @@ class DisplayGenerator {
node.dataset.sizeUnits = sizeUnits;
}
- const imageContainer = node.querySelector('.gloss-image-container');
imageContainer.style.width = `${usedWidth}em`;
if (typeof title === 'string') {
imageContainer.title = title;
}
- const aspectRatioSizer = node.querySelector('.gloss-image-aspect-ratio-sizer');
aspectRatioSizer.style.paddingTop = `${aspectRatio * 100.0}%`;
- const image = node.querySelector('img.gloss-image');
- image.dataset.pixelated = `${pixelated === true}`;
-
if (this._mediaLoader !== null) {
this._mediaLoader.loadMedia(
path,
dictionary,
- (url) => this._setImageData(node, image, url, false),
- () => this._setImageData(node, image, null, true)
+ (url) => this._setImageData(node, image, imageBackground, url, false),
+ () => this._setImageData(node, image, imageBackground, null, true)
);
}
return node;
}
- _setImageData(node, image, url, unloaded) {
+ _setImageData(node, image, imageBackground, url, unloaded) {
if (url !== null) {
image.src = url;
node.href = url;
node.dataset.imageLoadState = 'loaded';
+ imageBackground.style.setProperty('--image', `url("${url}")`);
} else {
image.removeAttribute('src');
node.removeAttribute('href');
node.dataset.imageLoadState = unloaded ? 'unloaded' : 'load-error';
+ imageBackground.style.removeProperty('--image');
}
}
diff --git a/ext/js/display/display.js b/ext/js/display/display.js
index ccca8229..26c1e06c 100644
--- a/ext/js/display/display.js
+++ b/ext/js/display/display.js
@@ -208,6 +208,10 @@ class Display extends EventDispatcher {
const {browser} = await yomichan.api.getEnvironmentInfo();
this._browser = browser;
+ if (documentElement !== null) {
+ documentElement.dataset.browser = browser;
+ }
+
// Prepare
await this._hotkeyHelpController.prepare();
await this._displayGenerator.prepare();
diff --git a/ext/js/language/dictionary-importer.js b/ext/js/language/dictionary-importer.js
index a0806a3a..b735953a 100644
--- a/ext/js/language/dictionary-importer.js
+++ b/ext/js/language/dictionary-importer.js
@@ -361,7 +361,19 @@ class DictionaryImporter {
}
async _createImageData(data, context, entry, attributes) {
- const {path, width: preferredWidth, height: preferredHeight, title, description, pixelated, collapsed, collapsible} = data;
+ const {
+ path,
+ width: preferredWidth,
+ height: preferredHeight,
+ title,
+ description,
+ pixelated,
+ imageRendering,
+ appearance,
+ background,
+ collapsed,
+ collapsible
+ } = data;
const {width, height} = await this._getImageMedia(path, context, entry);
const newData = Object.assign({}, attributes, {path, width, height});
if (typeof preferredWidth === 'number') { newData.preferredWidth = preferredWidth; }
@@ -369,6 +381,9 @@ class DictionaryImporter {
if (typeof title === 'string') { newData.title = title; }
if (typeof description === 'string') { newData.description = description; }
if (typeof pixelated === 'boolean') { newData.pixelated = pixelated; }
+ if (typeof imageRendering === 'string') { newData.imageRendering = imageRendering; }
+ if (typeof appearance === 'string') { newData.appearance = appearance; }
+ if (typeof background === 'boolean') { newData.background = background; }
if (typeof collapsed === 'boolean') { newData.collapsed = collapsed; }
if (typeof collapsible === 'boolean') { newData.collapsible = collapsible; }
return newData;