diff options
Diffstat (limited to 'ext')
| -rw-r--r-- | ext/css/display.css | 37 | ||||
| -rw-r--r-- | ext/data/schemas/dictionary-term-bank-v3-schema.json | 34 | ||||
| -rw-r--r-- | ext/display-templates.html | 10 | ||||
| -rw-r--r-- | ext/js/display/display-generator.js | 38 | ||||
| -rw-r--r-- | ext/js/display/display.js | 4 | ||||
| -rw-r--r-- | ext/js/language/dictionary-importer.js | 17 | 
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; |