« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/content/dependencies/generateAlbumCommentaryPage.js68
-rw-r--r--src/content/dependencies/generateAlbumCoverArtwork.js20
-rw-r--r--src/content/dependencies/generateContentHeading.js4
-rw-r--r--src/content/dependencies/generateCoverArtwork.js7
-rw-r--r--src/content/dependencies/generateTrackCoverArtwork.js32
-rw-r--r--src/content/dependencies/image.js34
-rw-r--r--src/content/dependencies/linkExternal.js9
-rw-r--r--src/content/dependencies/linkTrackDynamically.js34
-rw-r--r--src/content/dependencies/transformContent.js2
-rw-r--r--src/static/client3.js9
-rw-r--r--src/static/site5.css35
-rw-r--r--src/strings-default.yaml9
12 files changed, 217 insertions, 46 deletions
diff --git a/src/content/dependencies/generateAlbumCommentaryPage.js b/src/content/dependencies/generateAlbumCommentaryPage.js
index 001003ae..442d72a7 100644
--- a/src/content/dependencies/generateAlbumCommentaryPage.js
+++ b/src/content/dependencies/generateAlbumCommentaryPage.js
@@ -1,4 +1,4 @@
-import {stitchArrays} from '#sugar';
+import {empty, stitchArrays} from '#sugar';
 
 export default {
   contentDependencies: [
@@ -11,6 +11,7 @@ export default {
     'generateTrackCoverArtwork',
     'generatePageLayout',
     'linkAlbum',
+    'linkExternal',
     'linkTrack',
   ],
 
@@ -32,6 +33,15 @@ export default {
       relation('generateAlbumNavAccent', album, null);
 
     if (album.commentary) {
+      relations.albumCommentaryHeading =
+        relation('generateContentHeading');
+
+      relations.albumCommentaryLink =
+        relation('linkAlbum', album);
+
+      relations.albumCommentaryListeningLinks =
+        album.urls.map(url => relation('linkExternal', url));
+
       if (album.hasCoverArt) {
         relations.albumCommentaryCover =
           relation('generateAlbumCoverArtwork', album);
@@ -54,6 +64,11 @@ export default {
       tracksWithCommentary
         .map(track => relation('linkTrack', track));
 
+    relations.trackCommentaryListeningLinks =
+      tracksWithCommentary
+        .map(track =>
+          track.urls.map(url => relation('linkExternal', url)));
+
     relations.trackCommentaryCovers =
       tracksWithCommentary
         .map(track =>
@@ -142,9 +157,27 @@ export default {
             })),
 
           relations.albumCommentaryContent && [
-            html.tag('h3',
-              {class: ['content-heading']},
-              language.$('albumCommentaryPage.entry.title.albumCommentary')),
+            relations.albumCommentaryHeading.slots({
+              tag: 'h3',
+              color: data.color,
+
+              title:
+                language.$('albumCommentaryPage.entry.title.albumCommentary', {
+                  album: relations.albumCommentaryLink,
+                }),
+
+              accent:
+                !empty(relations.albumCommentaryListeningLinks) &&
+                  language.$('albumCommentaryPage.entry.title.albumCommentary.accent', {
+                    listeningLinks:
+                      language.formatUnitList(
+                        relations.albumCommentaryListeningLinks
+                          .map(link => link.slots({
+                            mode: 'album',
+                            tab: 'separate',
+                          }))),
+                  }),
+            }),
 
             relations.albumCommentaryCover
               ?.slots({mode: 'commentary'}),
@@ -156,15 +189,38 @@ export default {
           stitchArrays({
             heading: relations.trackCommentaryHeadings,
             link: relations.trackCommentaryLinks,
+            listeningLinks: relations.trackCommentaryListeningLinks,
             directory: data.trackCommentaryDirectories,
             cover: relations.trackCommentaryCovers,
             entries: relations.trackCommentaryEntries,
             color: data.trackCommentaryColors,
-          }).map(({heading, link, directory, cover, entries, color}) => [
+          }).map(({
+              heading,
+              link,
+              listeningLinks,
+              directory,
+              cover,
+              entries,
+              color,
+            }) => [
               heading.slots({
                 tag: 'h3',
                 id: directory,
-                title: link,
+                color,
+
+                title:
+                  language.$('albumCommentaryPage.entry.title.trackCommentary', {
+                    track: link,
+                  }),
+
+                accent:
+                  !empty(listeningLinks) &&
+                    language.$('albumCommentaryPage.entry.title.trackCommentary.accent', {
+                      listeningLinks:
+                        language.formatUnitList(
+                          listeningLinks.map(link =>
+                            link.slot('tab', 'separate'))),
+                    }),
               }),
 
               cover?.slots({mode: 'commentary'}),
diff --git a/src/content/dependencies/generateAlbumCoverArtwork.js b/src/content/dependencies/generateAlbumCoverArtwork.js
index cbec930e..ce8cde21 100644
--- a/src/content/dependencies/generateAlbumCoverArtwork.js
+++ b/src/content/dependencies/generateAlbumCoverArtwork.js
@@ -1,12 +1,22 @@
 export default {
   contentDependencies: ['generateCoverArtwork'],
 
-  relations: (relation, album) =>
-    ({coverArtwork: relation('generateCoverArtwork', album.artTags)}),
+  relations: (relation, album) => ({
+    coverArtwork:
+      relation('generateCoverArtwork', album.artTags),
+  }),
 
-  data: (album) =>
-    ({path: ['media.albumCover', album.directory, album.coverArtFileExtension]}),
+  data: (album) => ({
+    path:
+      ['media.albumCover', album.directory, album.coverArtFileExtension],
+
+    color:
+      album.color,
+  }),
 
   generate: (data, relations) =>
-    relations.coverArtwork.slot('path', data.path),
+    relations.coverArtwork.slots({
+      path: data.path,
+      color: data.color,
+    }),
 };
diff --git a/src/content/dependencies/generateContentHeading.js b/src/content/dependencies/generateContentHeading.js
index 56f68cb3..0343409c 100644
--- a/src/content/dependencies/generateContentHeading.js
+++ b/src/content/dependencies/generateContentHeading.js
@@ -29,7 +29,9 @@ export default {
               .slot('color', slots.color)
               .content,
       }, [
-        slots.title,
+        html.tag('span',
+          {[html.onlyIfContent]: true, class: 'content-heading-main-title'},
+          slots.title),
 
         html.tag('span',
           {[html.onlyIfContent]: true, class: 'content-heading-accent'},
diff --git a/src/content/dependencies/generateCoverArtwork.js b/src/content/dependencies/generateCoverArtwork.js
index aeba97de..e43963fb 100644
--- a/src/content/dependencies/generateCoverArtwork.js
+++ b/src/content/dependencies/generateCoverArtwork.js
@@ -31,6 +31,10 @@ export default {
       type: 'string',
     },
 
+    color: {
+      validate: v => v.isColor,
+    },
+
     mode: {
       validate: v => v.is('primary', 'thumbnail', 'commentary'),
       default: 'primary',
@@ -45,6 +49,7 @@ export default {
             .slots({
               path: slots.path,
               alt: slots.alt,
+              color: slots.color,
               thumb: 'medium',
               id: 'cover-art',
               reveal: true,
@@ -67,6 +72,7 @@ export default {
           .slots({
             path: slots.path,
             alt: slots.alt,
+            color: slots.color,
             thumb: 'small',
             reveal: false,
             link: false,
@@ -78,6 +84,7 @@ export default {
           .slots({
             path: slots.path,
             alt: slots.alt,
+            color: slots.color,
             thumb: 'medium',
             class: 'commentary-art',
             reveal: true,
diff --git a/src/content/dependencies/generateTrackCoverArtwork.js b/src/content/dependencies/generateTrackCoverArtwork.js
index ec0488e2..6c056c9a 100644
--- a/src/content/dependencies/generateTrackCoverArtwork.js
+++ b/src/content/dependencies/generateTrackCoverArtwork.js
@@ -1,20 +1,28 @@
 export default {
   contentDependencies: ['generateCoverArtwork'],
 
-  relations: (relation, track) =>
-    ({coverArtwork:
-        relation('generateCoverArtwork',
-          (track.hasUniqueCoverArt
-            ? track.artTags
-            : track.album.artTags))}),
-
-  data: (track) =>
-    ({path:
+  relations: (relation, track) => ({
+    coverArtwork:
+      relation('generateCoverArtwork',
         (track.hasUniqueCoverArt
-          ? ['media.trackCover', track.album.directory, track.directory, track.coverArtFileExtension]
-          : ['media.albumCover', track.album.directory, track.album.coverArtFileExtension])}),
+          ? track.artTags
+          : track.album.artTags)),
+  }),
+
+  data: (track) => ({
+    path:
+      (track.hasUniqueCoverArt
+        ? ['media.trackCover', track.album.directory, track.directory, track.coverArtFileExtension]
+        : ['media.albumCover', track.album.directory, track.album.coverArtFileExtension]),
+
+    color:
+      track.color,
+  }),
 
   generate: (data, relations) =>
-    relations.coverArtwork.slot('path', data.path),
+    relations.coverArtwork.slots({
+      path: data.path,
+      color: data.color,
+    }),
 };
 
diff --git a/src/content/dependencies/image.js b/src/content/dependencies/image.js
index 8aa9753b..3c78abe3 100644
--- a/src/content/dependencies/image.js
+++ b/src/content/dependencies/image.js
@@ -14,6 +14,12 @@ export default {
     'to',
   ],
 
+  contentDependencies: ['generateColorStyleVariables'],
+
+  relations: (relation) => ({
+    colorVariables: relation('generateColorStyleVariables'),
+  }),
+
   data(artTags) {
     const data = {};
 
@@ -43,6 +49,10 @@ export default {
       default: false,
     },
 
+    color: {
+      validate: v => v.isColor,
+    },
+
     reveal: {type: 'boolean', default: true},
     lazy: {type: 'boolean', default: false},
     square: {type: 'boolean', default: false},
@@ -56,7 +66,7 @@ export default {
     missingSourceContent: {type: 'html'},
   },
 
-  generate(data, slots, {
+  generate(data, relations, slots, {
     checkIfImagePathHasCachedThumbnails,
     getDimensionsOfImagePath,
     getSizeOfImagePath,
@@ -110,6 +120,12 @@ export default {
       !isMissingImageFile &&
       !empty(data.contentWarnings);
 
+    const colorStyle =
+      slots.color &&
+        relations.colorVariables
+          .slot('color', slots.color)
+          .content;
+
     const willSquare = slots.square;
 
     const idOnImg = willLink ? null : slots.id;
@@ -118,6 +134,9 @@ export default {
     const classOnImg = willLink ? null : slots.class;
     const classOnLink = willLink ? slots.class : null;
 
+    const styleOnContainer = willLink ? null : colorStyle;
+    const styleOnLink = willLink ? colorStyle : null;
+
     if (!originalSrc || isMissingImageFile) {
       return prepare(
         html.tag('div', {class: 'image-text-area'},
@@ -191,7 +210,7 @@ export default {
       imgAttributes['data-no-image-preview'] = true;
     }
 
-    // These attributes are only relevant when a thumbnail are available *and*
+    // These attributes are only relevant when a thumbnail is available *and*
     // being used.
     if (hasThumbnails && slots.thumb) {
       if (fileSize) {
@@ -238,9 +257,13 @@ export default {
       let wrapped = content;
 
       wrapped =
-        html.tag('div', {class: ['image-container', !originalSrc && 'placeholder-image']},
+        html.tag('div', {
+          class: ['image-container', !originalSrc && 'placeholder-image'],
+          style: styleOnContainer,
+        }, [
           html.tag('div', {class: 'image-inner-area'},
-            wrapped));
+            wrapped),
+        ]);
 
       if (willReveal) {
         wrapped =
@@ -270,6 +293,7 @@ export default {
         wrapped = html.tag('a',
           {
             id: idOnLink,
+
             class: [
               'box',
               'image-link',
@@ -277,6 +301,8 @@ export default {
               classOnLink,
             ],
 
+            style: styleOnLink,
+
             href:
               (typeof slots.link === 'string'
                 ? slots.link
diff --git a/src/content/dependencies/linkExternal.js b/src/content/dependencies/linkExternal.js
index 5de612e2..4a0959c0 100644
--- a/src/content/dependencies/linkExternal.js
+++ b/src/content/dependencies/linkExternal.js
@@ -24,6 +24,11 @@ export default {
       validate: v => v.is('generic', 'album', 'flash'),
       default: 'generic',
     },
+
+    tab: {
+      validate: v => v.is('default', 'separate'),
+      default: 'default',
+    },
   },
 
   generate(data, slots, {html, language}) {
@@ -53,6 +58,10 @@ export default {
       {
         href: data.url,
         class: 'nowrap',
+        target:
+          (slots.tab === 'separate'
+            ? '_blank'
+            : null),
       },
 
       // truly unhinged indentation here
diff --git a/src/content/dependencies/linkTrackDynamically.js b/src/content/dependencies/linkTrackDynamically.js
new file mode 100644
index 00000000..242cd4cb
--- /dev/null
+++ b/src/content/dependencies/linkTrackDynamically.js
@@ -0,0 +1,34 @@
+export default {
+  contentDependencies: ['linkTrack'],
+  extraDependencies: ['pagePath'],
+
+  relations: (relation, track) => ({
+    infoLink: relation('linkTrack', track),
+  }),
+
+  data: (track) => ({
+    trackDirectory:
+      track.directory,
+
+    albumDirectory:
+      track.album.directory,
+
+    trackHasCommentary:
+      !!track.commentary,
+  }),
+
+  generate(data, relations, {pagePath}) {
+    if (
+      pagePath[0] === 'albumCommentary' &&
+      pagePath[1] === data.albumDirectory &&
+      data.trackHasCommentary
+    ) {
+      relations.infoLink.setSlots({
+        anchor: true,
+        hash: data.trackDirectory,
+      });
+    }
+
+    return relations.infoLink;
+  },
+};
diff --git a/src/content/dependencies/transformContent.js b/src/content/dependencies/transformContent.js
index dab89630..a85ac158 100644
--- a/src/content/dependencies/transformContent.js
+++ b/src/content/dependencies/transformContent.js
@@ -130,7 +130,7 @@ const linkThingRelationMap = {
   newsEntry: 'linkNewsEntry',
   staticPage: 'linkStaticPage',
   tag: 'linkArtTag',
-  track: 'linkTrack',
+  track: 'linkTrackDynamically',
 };
 
 const linkValueRelationMap = {
diff --git a/src/static/client3.js b/src/static/client3.js
index 8372a268..6af548d9 100644
--- a/src/static/client3.js
+++ b/src/static/client3.js
@@ -899,11 +899,12 @@ function updateStickySubheadingContent(index) {
       child.remove();
     }
 
-    for (const child of closestHeading.childNodes) {
-      if (child.classList?.contains('content-heading-accent')) {
-        continue;
-      }
+    const textContainer =
+      closestHeading.querySelector('.content-heading-main-title')
+        // Just for compatibility with older builds of the site.
+        ?? closestHeading;
 
+    for (const child of textContainer.childNodes) {
       if (child.tagName === 'A') {
         for (const grandchild of child.childNodes) {
           stickySubheading.appendChild(grandchild.cloneNode(true));
diff --git a/src/static/site5.css b/src/static/site5.css
index dd16cbf9..218b4f97 100644
--- a/src/static/site5.css
+++ b/src/static/site5.css
@@ -554,6 +554,7 @@ p .current {
   width: 30%;
   max-width: 250px;
   margin: 15px 0 10px 20px;
+  box-shadow: 0 0 4px 5px rgba(0, 0, 0, 0.35);
 }
 
 .js-hide,
@@ -704,7 +705,7 @@ p code {
 }
 
 main.long-content {
-  --long-content-padding-ratio: 0.12;
+  --long-content-padding-ratio: 0.10;
 }
 
 main.long-content .main-content-container,
@@ -804,6 +805,17 @@ html[data-url-key="localized.albumCommentary"] li.no-commentary {
   opacity: 0.7;
 }
 
+html[data-url-key="localized.albumCommentary"] .content-heading-main-title {
+  margin-right: 0.25em;
+}
+
+html[data-url-key="localized.albumCommentary"] .content-heading-accent {
+  font-weight: normal;
+  font-style: oblique;
+  font-size: 0.9rem;
+  display: inline-block;
+}
+
 html[data-url-key="localized.listing"][data-url-value0="random"] #data-loading-line,
 html[data-url-key="localized.listing"][data-url-value0="random"] #data-loaded-line,
 html[data-url-key="localized.listing"][data-url-value0="random"] #data-error-line {
@@ -1291,12 +1303,6 @@ html[data-url-key="localized.home"] .carousel-container {
   animation-delay: 125ms;
 }
 
-.content-heading .content-heading-accent {
-  font-weight: normal;
-  font-size: 1rem;
-  margin-left: 0.25em;
-}
-
 h3.content-heading {
   clear: both;
 }
@@ -1678,6 +1684,13 @@ html[data-language-code="preview-en"][data-url-key="localized.home"] #content
  */
 
 @media (min-width: 600px) and (max-width: 899.98px) {
+  /* Medim layout is mainly defined (to the user) by hiding the sidebar, so
+   * don't apply the similar layout change of widening the long-content area
+   * if this page doesn't have a sidebar to hide in the first place.
+   */
+  #page-container:not(.has-zero-sidebars) main.long-content {
+    --long-content-padding-ratio: 0.06;
+  }
 }
 
 /* Layout - Wide or Medium */
@@ -1767,6 +1780,10 @@ html[data-language-code="preview-en"][data-url-key="localized.home"] #content
     max-width: unset;
   }
 
+  main.long-content {
+    --long-content-padding-ratio: 0.02;
+  }
+
   /* Show sticky heading above cover art */
 
   .content-sticky-heading-container {
@@ -1782,8 +1799,4 @@ html[data-language-code="preview-en"][data-url-key="localized.home"] #content
   #header > div:not(:first-child) {
     margin-top: 0.5em;
   }
-
-  main.long-content {
-    --long-content-padding-ratio: 0.04;
-  }
 }
diff --git a/src/strings-default.yaml b/src/strings-default.yaml
index 5a3d172f..46a592df 100644
--- a/src/strings-default.yaml
+++ b/src/strings-default.yaml
@@ -753,8 +753,13 @@ albumCommentaryPage:
 
   entry:
     title:
-      albumCommentary: "Album commentary"
-      trackCommentary: "{TRACK}"
+      albumCommentary:
+        _: "{ALBUM}"
+        accent: "Listen on: {LISTENING_LINKS}"
+
+      trackCommentary:
+        _: "{TRACK}"
+        accent: "Listen on: {LISTENING_LINKS}"
 
 #
 # artistInfoPage: