« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/content/dependencies/generateCoverArtwork.js24
-rw-r--r--src/content/dependencies/image.js78
-rw-r--r--src/content/dependencies/linkThing.js5
-rw-r--r--src/static/js/client/image-overlay.js3
4 files changed, 88 insertions, 22 deletions
diff --git a/src/content/dependencies/generateCoverArtwork.js b/src/content/dependencies/generateCoverArtwork.js
index 89b66ce0..616b3c95 100644
--- a/src/content/dependencies/generateCoverArtwork.js
+++ b/src/content/dependencies/generateCoverArtwork.js
@@ -122,6 +122,30 @@ export default {
                 thumb: 'medium',
                 reveal: true,
                 link: true,
+
+                responsiveThumb: true,
+                responsiveSizes:
+                  // No clamp(), min(), or max() here because Safari.
+                  // The boundaries here are mostly experimental, apart from
+                  // the ones which flat-out switch layouts.
+
+                  // Layout - Thin (phones)
+                  // Most of viewport width
+                  '(max-width: 600px) 90vw,\n' +
+
+                  // Layout - Medium
+                  // Sidebar is hidden; content area is by definition
+                  // most of the viewport
+                  '(max-width: 640px) 220px,\n' +
+                  '(max-width: 800px) 36vw,\n' +
+                  '(max-width: 850px) 280px,\n' +
+
+                  // Layout - Wide
+                  // Sidebar is visible; content area has its own maximum
+                  // Assume the sidebar is at minimum width
+                  '(max-width: 880px) 220px,\n' +
+                  '(max-width: 1050pz) calc(0.40 * (90vw - 150px - 10px)),\n' +
+                  '280px',
               }),
 
               slots.showOriginDetails &&
diff --git a/src/content/dependencies/image.js b/src/content/dependencies/image.js
index 1b6b08dd..d979b0bc 100644
--- a/src/content/dependencies/image.js
+++ b/src/content/dependencies/image.js
@@ -28,6 +28,8 @@ export default {
 
   slots: {
     thumb: {type: 'string'},
+    responsiveThumb: {type: 'boolean', default: false},
+    responsiveSizes: {type: 'string'},
 
     reveal: {type: 'boolean', default: true},
     lazy: {type: 'boolean', default: false},
@@ -199,31 +201,29 @@ export default {
     // so it won't be set if thumbnails aren't available.
     let revealSrc = null;
 
+    let originalDimensions;
+    let availableThumbs;
+    let selectedThumbtack;
+
+    const getThumbSrc = (thumbtack) =>
+      to('thumb.path', mediaSrc.replace(/\.(png|jpg)$/, `.${thumbtack}.jpg`));
+
     // If thumbnails are available *and* being used, calculate thumbSrc,
     // and provide some attributes relevant to the large image overlay.
     if (hasThumbnails && slots.thumb) {
-      const selectedSize =
+      selectedThumbtack =
         getThumbnailEqualOrSmaller(slots.thumb, mediaSrc);
 
-      const mediaSrcJpeg =
-        mediaSrc.replace(/\.(png|jpg)$/, `.${selectedSize}.jpg`);
-
       displaySrc =
-        to('thumb.path', mediaSrcJpeg);
+        getThumbSrc(selectedThumbtack);
 
       if (willReveal) {
-        const miniSize =
-          getThumbnailEqualOrSmaller('mini', mediaSrc);
-
-        const mediaSrcJpeg =
-          mediaSrc.replace(/\.(png|jpg)$/, `.${miniSize}.jpg`);
-
         revealSrc =
-          to('thumb.path', mediaSrcJpeg);
+          getThumbSrc(getThumbnailEqualOrSmaller('mini', mediaSrc));
       }
 
-      const originalDimensions = getDimensionsOfImagePath(mediaSrc);
-      const availableThumbs = getThumbnailsAvailableForDimensions(originalDimensions);
+      originalDimensions = getDimensionsOfImagePath(mediaSrc);
+      availableThumbs = getThumbnailsAvailableForDimensions(originalDimensions);
 
       const fileSize =
         (willLink && mediaSrc
@@ -239,11 +239,54 @@ export default {
         !empty(availableThumbs) &&
           {'data-thumbs':
               availableThumbs
-                .map(([name, size]) => `${name}:${size}`)
+                .map(([tack, size]) => `${tack}:${size}`)
                 .join(' ')},
       ]);
     }
 
+    let displayStaticImg =
+      html.tag('img',
+        imgAttributes,
+        {src: displaySrc});
+
+    if (hasThumbnails && slots.responsiveThumb) responsive: {
+      if (slots.lazy) {
+        logWarn`${'responsiveThumb'} and ${'lazy'} are used together, but not compatible`;
+        break responsive;
+      }
+
+      if (!slots.thumb) {
+        logWarn`${'responsiveThumb'} must be used alongside a default ${'thumb'}`;
+        break responsive;
+      }
+
+      const srcset = [
+        // Never load the original source, which might be a very large
+        // uncompressed file. Bah!
+        /* [originalSrc, `${Math.min(...originalDimensions)}w`], */
+
+        ...availableThumbs.map(([tack, size]) =>
+          [getThumbSrc(tack), `${Math.floor(0.95 * size)}w`]),
+
+        // fallback
+        [displaySrc],
+      ].map(line => line.join(' ')).join(',\n');
+
+      displayStaticImg =
+        html.tag('img',
+          imgAttributes,
+
+          {sizes:
+            (slots.responsiveSizes.match(/(?=(?:,|^))\s*\S/)
+                // slot provided fallback size
+              ? slots.responsiveSizes
+                // default fallback size
+              : slots.responsiveSizes + ',\n' +
+                new Map(availableThumbs).get(selectedThumbtack) + 'px')},
+
+          {srcset});
+    }
+
     if (!displaySrc) {
       return (
         prepare(
@@ -252,10 +295,7 @@ export default {
     }
 
     const images = {
-      displayStatic:
-        html.tag('img',
-          imgAttributes,
-          {src: displaySrc}),
+      displayStatic: displayStaticImg,
 
       displayLazy:
         slots.lazy &&
diff --git a/src/content/dependencies/linkThing.js b/src/content/dependencies/linkThing.js
index 7784afe7..166a857d 100644
--- a/src/content/dependencies/linkThing.js
+++ b/src/content/dependencies/linkThing.js
@@ -77,14 +77,15 @@ export default {
     const linkAttributes = slots.attributes;
     const wrapperAttributes = html.attributes();
 
+    const name =
+      relations.name.slot('preferShortName', slots.preferShortName);
+
     const showShortName =
       slots.preferShortName &&
      !data.nameText &&
       data.nameShort &&
       data.nameShort !== data.name;
 
-    const name = relations.name;
-
     const showWikiTooltip =
       (slots.tooltipStyle === 'auto'
         ? showShortName
diff --git a/src/static/js/client/image-overlay.js b/src/static/js/client/image-overlay.js
index 6809726a..0595bff7 100644
--- a/src/static/js/client/image-overlay.js
+++ b/src/static/js/client/image-overlay.js
@@ -147,7 +147,8 @@ function getImageLinkDetails(imageLink) {
       a.href,
 
     embeddedSrc:
-      img?.src ??
+      img?.src ||
+      img?.currentSrc ||
       a.dataset.embedSrc,
 
     originalFileSize: