« 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/generateArtistInfoPageArtworksChunk.js11
-rw-r--r--src/content/dependencies/generateArtistInfoPageChunk.js85
-rw-r--r--src/content/dependencies/generateArtistInfoPageCommentaryChunkedList.js91
-rw-r--r--src/content/dependencies/generateArtistInfoPageFlashesChunk.js8
-rw-r--r--src/content/dependencies/generateArtistInfoPageTracksChunk.js41
-rw-r--r--src/content/dependencies/generateContributionList.js6
-rw-r--r--src/content/dependencies/generateGroupInfoPageAlbumsListByDate.js6
-rw-r--r--src/content/dependencies/generateGroupInfoPageAlbumsListBySeries.js19
-rw-r--r--src/content/dependencies/generateNewsEntryReadAnotherLinks.js4
-rw-r--r--src/data/things/language.js58
-rw-r--r--src/search-select.js91
-rw-r--r--src/search.js3
-rw-r--r--src/static/css/site.css15
-rw-r--r--src/static/js/search-worker.js2
14 files changed, 291 insertions, 149 deletions
diff --git a/src/content/dependencies/generateArtistInfoPageArtworksChunk.js b/src/content/dependencies/generateArtistInfoPageArtworksChunk.js
index f4c9439a..eb15d54b 100644
--- a/src/content/dependencies/generateArtistInfoPageArtworksChunk.js
+++ b/src/content/dependencies/generateArtistInfoPageArtworksChunk.js
@@ -25,18 +25,19 @@ export default {
     },
   },
 
-  generate: (data, relations, slots) =>
+  generate: (data, relations, slots, {html}) =>
     relations.template.slots({
       mode: 'album',
-      albumLink: relations.albumLink,
+      link: relations.albumLink,
 
       dates:
         (slots.filterEditsForWiki
           ? Array.from({length: data.dates}, () => null)
           : data.dates),
 
-      items:
-        relations.items.map(item =>
-          item.slot('filterEditsForWiki', slots.filterEditsForWiki)),
+      list:
+        html.tag('ul',
+          relations.items.map(item =>
+            item.slot('filterEditsForWiki', slots.filterEditsForWiki))),
     }),
 };
diff --git a/src/content/dependencies/generateArtistInfoPageChunk.js b/src/content/dependencies/generateArtistInfoPageChunk.js
index 80429912..3fa46c61 100644
--- a/src/content/dependencies/generateArtistInfoPageChunk.js
+++ b/src/content/dependencies/generateArtistInfoPageChunk.js
@@ -8,17 +8,12 @@ export default {
 
     id: {type: 'string'},
 
-    albumLink: {
+    link: {
       type: 'html',
       mutable: false,
     },
 
-    flashActLink: {
-      type: 'html',
-      mutable: false,
-    },
-
-    items: {
+    list: {
       type: 'html',
       mutable: false,
     },
@@ -51,50 +46,43 @@ export default {
     }
 
     let accentedLink;
-
-    accent: {
-      switch (slots.mode) {
-        case 'album': {
-          accentedLink = slots.albumLink;
-
-          const options = {album: accentedLink};
-          const parts = ['artistPage.creditList.album'];
-
-          if (onlyDate) {
-            parts.push('withDate');
-            options.date = language.formatDate(onlyDate);
-          }
-
-          if (slots.duration) {
-            parts.push('withDuration');
-            options.duration =
-              language.formatDuration(slots.duration, {
-                approximate: slots.durationApproximate,
-              });
-          }
-
-          accentedLink = language.formatString(...parts, options);
-          break;
+    switch (slots.mode) {
+      case 'album': {
+        const options = {album: slots.link};
+        const parts = ['artistPage.creditList.album'];
+
+        if (onlyDate) {
+          parts.push('withDate');
+          options.date = language.formatDate(onlyDate);
         }
 
-        case 'flash': {
-          accentedLink = slots.flashActLink;
-
-          const options = {act: accentedLink};
-          const parts = ['artistPage.creditList.flashAct'];
+        if (slots.duration) {
+          parts.push('withDuration');
+          options.duration =
+            language.formatDuration(slots.duration, {
+              approximate: slots.durationApproximate,
+            });
+        }
 
-          if (onlyDate) {
-            parts.push('withDate');
-            options.date = language.formatDate(onlyDate);
-          } else if (earliestDate && latestDate) {
-            parts.push('withDateRange');
-            options.dateRange =
-              language.formatDateRange(earliestDate, latestDate);
-          }
+        accentedLink = language.formatString(...parts, options);
+        break;
+      }
 
-          accentedLink = language.formatString(...parts, options);
-          break;
+      case 'flash': {
+        const options = {act: slots.link};
+        const parts = ['artistPage.creditList.flashAct'];
+
+        if (onlyDate) {
+          parts.push('withDate');
+          options.date = language.formatDate(onlyDate);
+        } else if (earliestDate && latestDate) {
+          parts.push('withDateRange');
+          options.dateRange =
+            language.formatDateRange(earliestDate, latestDate);
         }
+
+        accentedLink = language.formatString(...parts, options);
+        break;
       }
     }
 
@@ -103,10 +91,7 @@ export default {
         slots.id && {id: slots.id},
         accentedLink),
 
-      html.tag('dd',
-        html.tag('ul',
-          {class: 'offset-tooltips'},
-          slots.items)),
+      html.tag('dd', slots.list),
     ]);
   },
 };
diff --git a/src/content/dependencies/generateArtistInfoPageCommentaryChunkedList.js b/src/content/dependencies/generateArtistInfoPageCommentaryChunkedList.js
index caec58d6..08446a2e 100644
--- a/src/content/dependencies/generateArtistInfoPageCommentaryChunkedList.js
+++ b/src/content/dependencies/generateArtistInfoPageCommentaryChunkedList.js
@@ -220,52 +220,57 @@ export default {
             (chunkType === 'album'
               ? chunk.slots({
                   mode: 'album',
-                  albumLink: chunkLink,
-                  items:
-                    stitchArrays({
-                      item: items,
-                      link: itemLinks,
-                      annotation: itemAnnotations,
-                      type: itemTypes,
-                    }).map(({item, link, annotation, type}) =>
-                      item.slots({
-                        annotation:
-                          annotation.slots({
-                            mode: 'inline',
-                            absorbPunctuationFollowingExternalLinks: false,
-                          }),
-
-                        content:
-                          (type === 'album'
-                            ? html.tag('i',
-                                language.$(capsule, 'album.commentary'))
-                            : language.$(capsule, 'track', {track: link})),
-                      })),
+                  link: chunkLink,
+
+                  list:
+                    html.tag('ul',
+                      stitchArrays({
+                        item: items,
+                        link: itemLinks,
+                        annotation: itemAnnotations,
+                        type: itemTypes,
+                      }).map(({item, link, annotation, type}) =>
+                        item.slots({
+                          annotation:
+                            annotation.slots({
+                              mode: 'inline',
+                              absorbPunctuationFollowingExternalLinks: false,
+                            }),
+
+                          content:
+                            (type === 'album'
+                              ? html.tag('i',
+                                  language.$(capsule, 'album.commentary'))
+                              : language.$(capsule, 'track', {track: link})),
+                        }))),
                 })
-           : chunkType === 'flash-act'
+
+             : chunkType === 'flash-act'
               ? chunk.slots({
                   mode: 'flash',
-                  flashActLink: chunkLink,
-                  items:
-                    stitchArrays({
-                      item: items,
-                      link: itemLinks,
-                      annotation: itemAnnotations,
-                    }).map(({item, link, annotation}) =>
-                      item.slots({
-                        annotation:
-                          (annotation
-                            ? annotation.slots({
-                                mode: 'inline',
-                                absorbPunctuationFollowingExternalLinks: false,
-                              })
-                            : null),
-
-                        content:
-                          language.$(capsule, 'flash', {
-                            flash: link,
-                          }),
-                      })),
+                  link: chunkLink,
+
+                  list:
+                    html.tag('ul',
+                      stitchArrays({
+                        item: items,
+                        link: itemLinks,
+                        annotation: itemAnnotations,
+                      }).map(({item, link, annotation}) =>
+                        item.slots({
+                          annotation:
+                            (annotation
+                              ? annotation.slots({
+                                  mode: 'inline',
+                                  absorbPunctuationFollowingExternalLinks: false,
+                                })
+                              : null),
+
+                          content:
+                            language.$(capsule, 'flash', {
+                              flash: link,
+                            }),
+                        }))),
                 })
               : null)))),
 };
diff --git a/src/content/dependencies/generateArtistInfoPageFlashesChunk.js b/src/content/dependencies/generateArtistInfoPageFlashesChunk.js
index acdb9897..ce89d80c 100644
--- a/src/content/dependencies/generateArtistInfoPageFlashesChunk.js
+++ b/src/content/dependencies/generateArtistInfoPageFlashesChunk.js
@@ -18,11 +18,13 @@ export default {
         .map(contrib => contrib.date),
   }),
 
-  generate: (data, relations) =>
+  generate: (data, relations, {html}) =>
     relations.template.slots({
       mode: 'flash',
-      flashActLink: relations.flashActLink,
+      link: relations.flashActLink,
       dates: data.dates,
-      items: relations.items,
+
+      list:
+        html.tag('ul', relations.items),
     }),
 };
diff --git a/src/content/dependencies/generateArtistInfoPageTracksChunk.js b/src/content/dependencies/generateArtistInfoPageTracksChunk.js
index 3e4cc4e9..7d00fdd6 100644
--- a/src/content/dependencies/generateArtistInfoPageTracksChunk.js
+++ b/src/content/dependencies/generateArtistInfoPageTracksChunk.js
@@ -1,4 +1,5 @@
-import {unique} from '#sugar';
+import {sortAlbumsTracksChronologically} from '#sort';
+import {empty, unique} from '#sugar';
 import {getTotalDuration} from '#wiki-data';
 
 export default {
@@ -18,7 +19,7 @@ export default {
           trackContribs)),
   }),
 
-  data(_artist, album, trackContribLists) {
+  data(artist, album, trackContribLists) {
     const data = {};
 
     const contribs =
@@ -43,19 +44,47 @@ export default {
     data.durationApproximate =
       durationTerms.length > 1;
 
+    const tracks =
+      trackContribLists.map(contribs => contribs[0].thing);
+
+    data.numLinkingOtherReleases =
+      tracks.filter(track => {
+        if (empty(track.otherReleases)) return false;
+
+        const releases =
+          sortAlbumsTracksChronologically(track.allReleases.slice());
+
+        // later releases always link to first release
+        if (track !== releases[0]) return true;
+
+        // first releases only link to later credited releases
+        return tracks.slice(1).some(track => {
+          const contribs = [
+            ...track.artistContribs,
+            ...track.contributorContribs,
+          ];
+
+          return contribs.some(contrib => contrib.artist === artist);
+        });
+      }).length;
+
     return data;
   },
 
-  generate: (data, relations) =>
+  generate: (data, relations, {html}) =>
     relations.template.slots({
       mode: 'album',
-
-      albumLink: relations.albumLink,
+      link: relations.albumLink,
 
       dates: data.dates,
       duration: data.duration,
       durationApproximate: data.durationApproximate,
 
-      items: relations.items,
+      list:
+        html.tag('ul',
+          data.numLinkingOtherReleases > 1 &&
+            {class: 'offset-tooltips'},
+
+          relations.items),
     }),
 };
diff --git a/src/content/dependencies/generateContributionList.js b/src/content/dependencies/generateContributionList.js
index 3716bcd6..4f68321f 100644
--- a/src/content/dependencies/generateContributionList.js
+++ b/src/content/dependencies/generateContributionList.js
@@ -9,10 +9,14 @@ export default {
     chronologyKind: {type: 'string'},
   },
 
-  generate: (relations, slots, {html}) =>
+  generate: (relations, slots, {html, language}) =>
     html.tag('ul',
       {[html.onlyIfContent]: true},
 
+      relations.contributionLinks.length > 1 &&
+      language.$order('misc.artistLink.withContribution', 0) === 'ARTIST' &&
+        {class: 'offset-tooltips'},
+
       relations.contributionLinks
         .map(contributionLink =>
           html.tag('li',
diff --git a/src/content/dependencies/generateGroupInfoPageAlbumsListByDate.js b/src/content/dependencies/generateGroupInfoPageAlbumsListByDate.js
index de55f33a..bd3f5dd5 100644
--- a/src/content/dependencies/generateGroupInfoPageAlbumsListByDate.js
+++ b/src/content/dependencies/generateGroupInfoPageAlbumsListByDate.js
@@ -29,12 +29,16 @@ export default {
     },
   },
 
-  generate: (relations, slots, {html}) =>
+  generate: (relations, slots, {html, language}) =>
     html.tag('ul',
       {id: 'group-album-list-by-date'},
 
       slots.hidden && {style: 'display: none'},
 
+      relations.items.length > 1&&
+      language.$order('groupInfoPage.albumList.item.withYear', 0) === 'YEAR_ACCENT' &&
+        {class: 'offset-tooltips'},
+
       {[html.onlyIfContent]: true},
 
       relations.items
diff --git a/src/content/dependencies/generateGroupInfoPageAlbumsListBySeries.js b/src/content/dependencies/generateGroupInfoPageAlbumsListBySeries.js
index f8314d71..ddba0aec 100644
--- a/src/content/dependencies/generateGroupInfoPageAlbumsListBySeries.js
+++ b/src/content/dependencies/generateGroupInfoPageAlbumsListBySeries.js
@@ -12,6 +12,10 @@ export default {
       group.serieses
         .map(() => relation('generateContentHeading')),
 
+    seriesDescriptions:
+      group.serieses
+        .map(series => relation('transformContent', series.description)),
+
     seriesItems:
       group.serieses
         .map(series => series.albums
@@ -44,17 +48,23 @@ export default {
         {id: 'group-album-list-by-series'},
         {class: 'group-series-list'},
 
+        relations.seriesItems.flat().length > 1 &&
+        language.$order(listCapsule, 'item.withYear', 0) === 'YEAR_ACCENT' &&
+          {class: 'offset-tooltips'},
+
         {[html.onlyIfContent]: true},
 
         stitchArrays({
           name: data.seriesNames,
           itemsShowArtists: data.seriesItemsShowArtists,
           heading: relations.seriesHeadings,
+          description: relations.seriesDescriptions,
           items: relations.seriesItems,
         }).map(({
             name,
             itemsShowArtists,
             heading,
+            description,
             items,
           }) =>
             html.tags([
@@ -66,7 +76,11 @@ export default {
                   }),
               }),
 
-              html.tag('dd',
+              html.tag('dd', [
+                html.tag('blockquote',
+                  {[html.onlyIfContent]: true},
+                  description),
+
                 html.tag('ul',
                   stitchArrays({
                     item: items,
@@ -75,6 +89,7 @@ export default {
                       item.slots({
                         accentMode:
                           (showArtists ? 'artists' : null),
-                      })))),
+                      }))),
+              ]),
             ])))),
 };
diff --git a/src/content/dependencies/generateNewsEntryReadAnotherLinks.js b/src/content/dependencies/generateNewsEntryReadAnotherLinks.js
index 1f6ee6d4..50c23513 100644
--- a/src/content/dependencies/generateNewsEntryReadAnotherLinks.js
+++ b/src/content/dependencies/generateNewsEntryReadAnotherLinks.js
@@ -70,12 +70,16 @@ export default {
       entryLines.push(language.$(...parts, options));
     }
 
+    console.log(language.$order(prefix, 'previous.withDate', 0));
+
     return (
       html.tag('p', {class: 'read-another-links'},
         {[html.onlyIfContent]: true},
         {[html.joinChildren]: html.tag('br')},
 
         entryLines.length > 1 &&
+        language.$order(prefix, 'previous.withDate', 0) === 'DATE' &&
+        language.$order(prefix, 'next.withDate', 0) === 'DATE' &&
           {class: 'offset-tooltips'},
 
         entryLines));
diff --git a/src/data/things/language.js b/src/data/things/language.js
index 43f69f3d..5866027d 100644
--- a/src/data/things/language.js
+++ b/src/data/things/language.js
@@ -158,6 +158,10 @@ export class Language extends Thing {
     return this.formatString(...args);
   }
 
+  $order(...args) {
+    return this.orderStringOptions(...args);
+  }
+
   assertIntlAvailable(property) {
     if (!this[property]) {
       throw new Error(`Intl API ${property} unavailable`);
@@ -190,19 +194,14 @@ export class Language extends Thing {
     const key =
       this.#joinKeyParts(hasOptions ? args.slice(0, -1) : args);
 
+    const template =
+      this.#getStringTemplateFromFormedKey(key);
+
     const options =
       (hasOptions
         ? args.at(-1)
         : {});
 
-    if (!this.strings) {
-      throw new Error(`Strings unavailable`);
-    }
-
-    if (!this.validKeys.includes(key)) {
-      throw new Error(`Invalid key ${key} accessed`);
-    }
-
     const constantCasify = name =>
       name
         .replace(/[A-Z]/g, '_$&')
@@ -243,8 +242,7 @@ export class Language extends Thing {
         ]));
 
     const output = this.#iterateOverTemplate({
-      template: this.strings[key],
-
+      template,
       match: languageOptionRegex,
 
       insert: ({name: optionName}, canceledForming) => {
@@ -324,6 +322,46 @@ export class Language extends Thing {
     return output;
   }
 
+  orderStringOptions(...args) {
+    let slice = null, at = null, parts = null;
+    if (args.length >= 2 && typeof args.at(-1) === 'number') {
+      if (args.length >= 3 && typeof args.at(-2) === 'number') {
+        slice = [args.at(-2), args.at(-1)];
+        parts = args.slice(0, -2);
+      } else {
+        at = args.at(-1);
+        parts = args.slice(0, -1);
+      }
+    } else {
+      parts = args;
+    }
+
+    const template = this.getStringTemplate(...parts);
+    const matches = Array.from(template.matchAll(languageOptionRegex));
+    const options = matches.map(({groups}) => groups.name);
+
+    if (slice !== null) return options.slice(...slice);
+    if (at !== null) return options.at(at);
+    return options;
+  }
+
+  getStringTemplate(...args) {
+    const key = this.#joinKeyParts(args);
+    return this.#getStringTemplateFromFormedKey(key);
+  }
+
+  #getStringTemplateFromFormedKey(key) {
+    if (!this.strings) {
+      throw new Error(`Strings unavailable`);
+    }
+
+    if (!this.validKeys.includes(key)) {
+      throw new Error(`Invalid key ${key} accessed`);
+    }
+
+    return this.strings[key];
+  }
+
   #iterateOverTemplate({
     template,
     match: regexp,
diff --git a/src/search-select.js b/src/search-select.js
index 24532cbb..36b9e98a 100644
--- a/src/search-select.js
+++ b/src/search-select.js
@@ -3,6 +3,7 @@
 // These files totally go together, so read them side by side, okay?
 
 import baseSearchSpec from '#search-shape';
+import {unique} from '#sugar';
 import {getKebabCase} from '#wiki-data';
 
 function prepareArtwork(artwork, thing, {
@@ -52,6 +53,58 @@ function prepareArtwork(artwork, thing, {
   return serializeSrc;
 }
 
+function determineArtistGroups(artist, opts) {
+  const contributions = [
+    artist.musicContributions,
+    artist.artworkContributions
+      .filter(contrib => !contrib.annotation?.includes('edits for wiki')),
+  ].flat();
+
+  const contributionGroups =
+    contributions.flatMap(contrib => contrib.groups);
+
+  const scores =
+    new Map(
+      unique(contributionGroups).map(group => [group, 0]));
+
+  const artistNamesish =
+    unique(
+      [artist.name, ...artist.artistAliases.map(alias => alias.name)]
+        .map(name => getKebabCase(name)));
+
+  for (const group of scores.keys()) {
+    if (artistNamesish.includes(getKebabCase(group.name))) {
+      scores.delete(group);
+    }
+  }
+
+  for (const group of contributionGroups) {
+    scores.set(group, scores.get(group) + 1 / contributions.length);
+  }
+
+  const dividingGroups =
+    opts.wikiInfo.divideTrackListsByGroups;
+
+  const dividingGroupThreshold =
+    (contributions.length < 50 ? 0.08 : 0.16);
+
+  const generalGroupThreshold =
+    (contributions.length < 50 ? 0.00 : 0.12);
+
+  for (const group of scores.keys()) {
+    const threshold =
+      (dividingGroups.includes(group)
+        ? dividingGroupThreshold
+        : generalGroupThreshold);
+
+    if (scores.get(group) < threshold) {
+      scores.delete(group);
+    }
+  }
+
+  return Array.from(scores.keys());
+}
+
 function baselineProcess(thing, _opts) {
   const fields = {};
 
@@ -116,30 +169,24 @@ function genericSelect(wikiData) {
 function genericProcess(thing, opts) {
   const fields = baselineProcess(thing, opts);
 
-  const kind =
-    thing.constructor[Symbol.for('Thing.referenceType')];
-
   const boundPrepareArtwork = artwork =>
     prepareArtwork(artwork, thing, opts);
 
   fields.artwork =
-    (kind === 'track' && thing.hasUniqueCoverArt
+    (thing.isTrack && thing.hasUniqueCoverArt
       ? boundPrepareArtwork(thing.trackArtworks[0])
-   : kind === 'track'
+   : thing.isTrack
       ? boundPrepareArtwork(thing.album.coverArtworks[0])
-   : kind === 'album'
+   : thing.isAlbum
       ? boundPrepareArtwork(thing.coverArtworks[0])
-   : kind === 'flash'
+   : thing.isFlash
       ? boundPrepareArtwork(thing.coverArtwork)
       : null);
 
   fields.parentName =
-    (kind === 'track'
-      ? thing.album.name
-   : kind === 'group'
-      ? thing.category.name
-   : kind === 'flash'
-      ? thing.act.name
+    (thing.isTrack ? thing.album.name
+   : thing.isGroup ? thing.category.name
+   : thing.isFlash ? thing.act.name
       : null);
 
   fields.disambiguator =
@@ -147,9 +194,9 @@ function genericProcess(thing, opts) {
 
   fields.artTags =
     (Array.from(new Set(
-      (kind === 'track'
+      (thing.isTrack
         ? thing.trackArtworks.flatMap(artwork => artwork.artTags)
-     : kind === 'album'
+     : thing.isAlbum
         ? thing.coverArtworks.flatMap(artwork => artwork.artTags)
         : []))))
 
@@ -169,22 +216,20 @@ function genericProcess(thing, opts) {
 
   const contributions =
     contribKeys
-      .filter(key => Object.hasOwn(thing, key))
-      .flatMap(key => thing[key]);
+      .flatMap(key => thing[key] ?? []);
 
   fields.contributors =
     contributions
       .flatMap(({artist}) => [
         artist.name,
-        ...artist.aliasNames,
+        ...artist.artistAliases.map(alias => alias.name),
       ]);
 
   const groups =
-     (Object.hasOwn(thing, 'groups')
-       ? thing.groups
-    : Object.hasOwn(thing, 'album')
-       ? thing.album.groups
-       : []);
+    (thing.isAlbum ? thing.groups
+   : thing.isTrack ? thing.album.groups
+   : thing.isArtist ? determineArtistGroups(thing, opts)
+   : []);
 
   const mainContributorNames =
     contributions
diff --git a/src/search.js b/src/search.js
index 138a2d2c..bef8107f 100644
--- a/src/search.js
+++ b/src/search.js
@@ -23,9 +23,12 @@ function bindSearchUtilities({
   getThumbnailEqualOrSmaller,
   thumbsCache,
   urls,
+  wikiData,
 }) {
   const bound = {
     urls,
+    wikiData,
+    wikiInfo: wikiData.wikiInfo,
   };
 
   bound.checkIfImagePathHasCachedThumbnails =
diff --git a/src/static/css/site.css b/src/static/css/site.css
index a78a31fb..e1654e6d 100644
--- a/src/static/css/site.css
+++ b/src/static/css/site.css
@@ -1261,8 +1261,7 @@ label > input[type=checkbox]:not(:checked) + span {
   font-size: 0.9rem;
 }
 
-li:not(:first-child:last-child) .tooltip:where(:not(.cover-artwork .tooltip)),
-.offset-tooltips > :not(:first-child:last-child) .tooltip {
+.offset-tooltips .tooltip {
   left: 14px;
 }
 
@@ -2353,17 +2352,23 @@ li .origin-details {
   text-indent: 0;
 }
 
-.album-group-list blockquote {
+blockquote:is(
+  .album-group-list *, .group-series-list *
+) {
   max-width: 540px;
   margin-bottom: 9px;
   margin-top: 3px;
 }
 
-.album-group-list blockquote p:first-child {
+blockquote p:first-child:is(
+  .album-group-list *, .group-series-list *
+) {
   margin-top: 0;
 }
 
-.album-group-list blockquote p:last-child {
+blockquote p:last-child:is(
+  .album-group-list *, .group-series-list *
+) {
   margin-bottom: 0;
 }
 
diff --git a/src/static/js/search-worker.js b/src/static/js/search-worker.js
index 96ad8a0b..92ba1f0d 100644
--- a/src/static/js/search-worker.js
+++ b/src/static/js/search-worker.js
@@ -391,12 +391,14 @@ function performSearchAction({query, options}) {
 
 const interestingFieldCombinations = [
   ['primaryName'],
+  ['additionalNames'],
 
   ['primaryName', 'parentName', 'groups'],
   ['primaryName', 'parentName'],
   ['primaryName', 'groups', 'contributors'],
   ['primaryName', 'groups', 'artTags'],
   ['primaryName', 'groups'],
+  ['additionalNames', 'groups'],
   ['primaryName', 'contributors'],
   ['primaryName', 'artTags'],
   ['parentName', 'groups', 'artTags'],