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
This commit is contained in:
parent
3a095b1f6c
commit
7ae964c830
@ -1566,6 +1566,8 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
|
|||||||
line-height: 0;
|
line-height: 0;
|
||||||
font-size: calc(1em / var(--font-size-no-units));
|
font-size: calc(1em / var(--font-size-no-units));
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.gloss-image-link[data-background=true]>.gloss-image-container {
|
||||||
background-color: var(--gloss-image-background-color);
|
background-color: var(--gloss-image-background-color);
|
||||||
}
|
}
|
||||||
.gloss-image-link {
|
.gloss-image-link {
|
||||||
@ -1600,6 +1602,18 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 0.25em;
|
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 {
|
.gloss-image {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
@ -1617,13 +1631,27 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
|
|||||||
.gloss-image:not([src]) {
|
.gloss-image:not([src]) {
|
||||||
display: none;
|
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: auto;
|
||||||
image-rendering: -moz-crisp-edges;
|
image-rendering: -moz-crisp-edges;
|
||||||
image-rendering: -webkit-optimize-contrast;
|
image-rendering: -webkit-optimize-contrast;
|
||||||
image-rendering: pixelated;
|
image-rendering: pixelated;
|
||||||
image-rendering: crisp-edges;
|
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 {
|
.gloss-image-link[data-has-aspect-ratio=true] .gloss-image-aspect-ratio-sizer {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 0;
|
width: 0;
|
||||||
@ -1645,6 +1673,13 @@ button.definition-item-expansion-button:focus:focus-visible+.definition-item-con
|
|||||||
white-space: pre-line;
|
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 {
|
.gloss-image-link[data-size-units=em] .gloss-image-container {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,23 @@
|
|||||||
"description": "Whether or not the image should appear pixelated at sizes larger than the image's native resolution.",
|
"description": "Whether or not the image should appear pixelated at sizes larger than the image's native resolution.",
|
||||||
"default": false
|
"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": {
|
"collapsed": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not the image is collapsed by default.",
|
"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.",
|
"description": "Whether or not the image should appear pixelated at sizes larger than the image's native resolution.",
|
||||||
"default": false
|
"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": {
|
"collapsed": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether or not the image is collapsed by default.",
|
"description": "Whether or not the image is collapsed by default.",
|
||||||
|
@ -57,7 +57,15 @@
|
|||||||
</li></template>
|
</li></template>
|
||||||
<template id="definition-disambiguation-template"><span class="definition-disambiguation"></span></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-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="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>
|
<template id="inflection-template"><span class="inflection"></span><span class="inflection-separator"> </span></template>
|
||||||
|
|
||||||
|
@ -340,7 +340,22 @@ class DisplayGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_createDefinitionImage(data, dictionary) {
|
_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 hasPreferredWidth = (typeof preferredWidth === 'number');
|
||||||
const hasPreferredHeight = (typeof preferredHeight === 'number');
|
const hasPreferredHeight = (typeof preferredHeight === 'number');
|
||||||
@ -356,10 +371,18 @@ class DisplayGenerator {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const node = this._templates.instantiate('gloss-item-image');
|
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.path = path;
|
||||||
node.dataset.dictionary = dictionary;
|
node.dataset.dictionary = dictionary;
|
||||||
node.dataset.imageLoadState = 'not-loaded';
|
node.dataset.imageLoadState = 'not-loaded';
|
||||||
node.dataset.hasAspectRatio = 'true';
|
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.collapsed = typeof collapsed === 'boolean' ? `${collapsed}` : 'false';
|
||||||
node.dataset.collapsible = typeof collapsible === 'boolean' ? `${collapsible}` : 'true';
|
node.dataset.collapsible = typeof collapsible === 'boolean' ? `${collapsible}` : 'true';
|
||||||
if (typeof verticalAlign === 'string') {
|
if (typeof verticalAlign === 'string') {
|
||||||
@ -369,39 +392,36 @@ class DisplayGenerator {
|
|||||||
node.dataset.sizeUnits = sizeUnits;
|
node.dataset.sizeUnits = sizeUnits;
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageContainer = node.querySelector('.gloss-image-container');
|
|
||||||
imageContainer.style.width = `${usedWidth}em`;
|
imageContainer.style.width = `${usedWidth}em`;
|
||||||
if (typeof title === 'string') {
|
if (typeof title === 'string') {
|
||||||
imageContainer.title = title;
|
imageContainer.title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
const aspectRatioSizer = node.querySelector('.gloss-image-aspect-ratio-sizer');
|
|
||||||
aspectRatioSizer.style.paddingTop = `${aspectRatio * 100.0}%`;
|
aspectRatioSizer.style.paddingTop = `${aspectRatio * 100.0}%`;
|
||||||
|
|
||||||
const image = node.querySelector('img.gloss-image');
|
|
||||||
image.dataset.pixelated = `${pixelated === true}`;
|
|
||||||
|
|
||||||
if (this._mediaLoader !== null) {
|
if (this._mediaLoader !== null) {
|
||||||
this._mediaLoader.loadMedia(
|
this._mediaLoader.loadMedia(
|
||||||
path,
|
path,
|
||||||
dictionary,
|
dictionary,
|
||||||
(url) => this._setImageData(node, image, url, false),
|
(url) => this._setImageData(node, image, imageBackground, url, false),
|
||||||
() => this._setImageData(node, image, null, true)
|
() => this._setImageData(node, image, imageBackground, null, true)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
_setImageData(node, image, url, unloaded) {
|
_setImageData(node, image, imageBackground, url, unloaded) {
|
||||||
if (url !== null) {
|
if (url !== null) {
|
||||||
image.src = url;
|
image.src = url;
|
||||||
node.href = url;
|
node.href = url;
|
||||||
node.dataset.imageLoadState = 'loaded';
|
node.dataset.imageLoadState = 'loaded';
|
||||||
|
imageBackground.style.setProperty('--image', `url("${url}")`);
|
||||||
} else {
|
} else {
|
||||||
image.removeAttribute('src');
|
image.removeAttribute('src');
|
||||||
node.removeAttribute('href');
|
node.removeAttribute('href');
|
||||||
node.dataset.imageLoadState = unloaded ? 'unloaded' : 'load-error';
|
node.dataset.imageLoadState = unloaded ? 'unloaded' : 'load-error';
|
||||||
|
imageBackground.style.removeProperty('--image');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,6 +208,10 @@ class Display extends EventDispatcher {
|
|||||||
const {browser} = await yomichan.api.getEnvironmentInfo();
|
const {browser} = await yomichan.api.getEnvironmentInfo();
|
||||||
this._browser = browser;
|
this._browser = browser;
|
||||||
|
|
||||||
|
if (documentElement !== null) {
|
||||||
|
documentElement.dataset.browser = browser;
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare
|
// Prepare
|
||||||
await this._hotkeyHelpController.prepare();
|
await this._hotkeyHelpController.prepare();
|
||||||
await this._displayGenerator.prepare();
|
await this._displayGenerator.prepare();
|
||||||
|
@ -361,7 +361,19 @@ class DictionaryImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _createImageData(data, context, entry, attributes) {
|
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 {width, height} = await this._getImageMedia(path, context, entry);
|
||||||
const newData = Object.assign({}, attributes, {path, width, height});
|
const newData = Object.assign({}, attributes, {path, width, height});
|
||||||
if (typeof preferredWidth === 'number') { newData.preferredWidth = preferredWidth; }
|
if (typeof preferredWidth === 'number') { newData.preferredWidth = preferredWidth; }
|
||||||
@ -369,6 +381,9 @@ class DictionaryImporter {
|
|||||||
if (typeof title === 'string') { newData.title = title; }
|
if (typeof title === 'string') { newData.title = title; }
|
||||||
if (typeof description === 'string') { newData.description = description; }
|
if (typeof description === 'string') { newData.description = description; }
|
||||||
if (typeof pixelated === 'boolean') { newData.pixelated = pixelated; }
|
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 collapsed === 'boolean') { newData.collapsed = collapsed; }
|
||||||
if (typeof collapsible === 'boolean') { newData.collapsible = collapsible; }
|
if (typeof collapsible === 'boolean') { newData.collapsible = collapsible; }
|
||||||
return newData;
|
return newData;
|
||||||
|
BIN
test/data/dictionaries/valid-dictionary1/character.gif
Normal file
BIN
test/data/dictionaries/valid-dictionary1/character.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 107 B |
@ -36,6 +36,29 @@
|
|||||||
"naiyou definition 6: ",
|
"naiyou definition 6: ",
|
||||||
{"tag": "ruby", "content": ["内", {"tag": "rp", "content": "("}, {"tag": "rt", "content": "ない"}, {"tag": "rp", "content": ")"}]},
|
{"tag": "ruby", "content": ["内", {"tag": "rp", "content": "("}, {"tag": "rt", "content": "ない"}, {"tag": "rp", "content": ")"}]},
|
||||||
{"tag": "ruby", "content": ["容", {"tag": "rp", "content": "("}, {"tag": "rt", "content": "よう"}, {"tag": "rp", "content": ")"}]}
|
{"tag": "ruby", "content": ["容", {"tag": "rp", "content": "("}, {"tag": "rt", "content": "よう"}, {"tag": "rp", "content": ")"}]}
|
||||||
|
]},
|
||||||
|
{"type": "structured-content", "content": [
|
||||||
|
"imageRendering=auto: ",
|
||||||
|
{"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "auto", "collapsible": false, "collapsed": false, "sizeUnits": "em"},
|
||||||
|
"莢 ",
|
||||||
|
{"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "auto", "background": false, "collapsible": false, "collapsed": false, "sizeUnits": "em"},
|
||||||
|
"莢 ",
|
||||||
|
{"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "auto", "background": false, "appearance": "monochrome", "collapsible": false, "collapsed": false, "sizeUnits": "em"},
|
||||||
|
"莢\n",
|
||||||
|
"imageRendering=pixelated: ",
|
||||||
|
{"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "pixelated", "collapsible": false, "collapsed": false, "sizeUnits": "em"},
|
||||||
|
"莢 ",
|
||||||
|
{"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "pixelated", "background": false, "collapsible": false, "collapsed": false, "sizeUnits": "em"},
|
||||||
|
"莢 ",
|
||||||
|
{"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "pixelated", "background": false, "appearance": "monochrome", "collapsible": false, "collapsed": false, "sizeUnits": "em"},
|
||||||
|
"莢\n",
|
||||||
|
"imageRendering=crisp-edges: ",
|
||||||
|
{"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "crisp-edges", "collapsible": false, "collapsed": false, "sizeUnits": "em"},
|
||||||
|
"莢 ",
|
||||||
|
{"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "crisp-edges", "background": false, "collapsible": false, "collapsed": false, "sizeUnits": "em"},
|
||||||
|
"莢 ",
|
||||||
|
{"tag": "img", "path": "character.gif", "width": 1, "height": 1, "imageRendering": "crisp-edges", "background": false, "appearance": "monochrome", "collapsible": false, "collapsed": false, "sizeUnits": "em"},
|
||||||
|
"莢\n"
|
||||||
]}
|
]}
|
||||||
],
|
],
|
||||||
9, "P E1"
|
9, "P E1"
|
||||||
|
@ -162,8 +162,8 @@ async function testDatabase1() {
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
vm.assert.deepStrictEqual(counts, {
|
vm.assert.deepStrictEqual(counts, {
|
||||||
counts: [{kanji: 2, kanjiMeta: 2, terms: 15, termMeta: 12, tagMeta: 15, media: 1}],
|
counts: [{kanji: 2, kanjiMeta: 2, terms: 15, termMeta: 12, tagMeta: 15, media: 2}],
|
||||||
total: {kanji: 2, kanjiMeta: 2, terms: 15, termMeta: 12, tagMeta: 15, media: 1}
|
total: {kanji: 2, kanjiMeta: 2, terms: 15, termMeta: 12, tagMeta: 15, media: 2}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Test find* functions
|
// Test find* functions
|
||||||
|
Loading…
Reference in New Issue
Block a user