« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/content
diff options
context:
space:
mode:
Diffstat (limited to 'src/content')
-rw-r--r--src/content/dependencies/generateAlbumReleaseInfo.js1
-rw-r--r--src/content/dependencies/generateAlbumTrackListItem.js32
-rw-r--r--src/content/dependencies/generateArtistCredit.js180
-rw-r--r--src/content/dependencies/generateReleaseInfoContributionsLine.js10
-rw-r--r--src/content/dependencies/generateTrackReleaseInfo.js1
5 files changed, 159 insertions, 65 deletions
diff --git a/src/content/dependencies/generateAlbumReleaseInfo.js b/src/content/dependencies/generateAlbumReleaseInfo.js
index 28227f45..217282c0 100644
--- a/src/content/dependencies/generateAlbumReleaseInfo.js
+++ b/src/content/dependencies/generateAlbumReleaseInfo.js
@@ -69,6 +69,7 @@ export default {
           [
             relations.artistContributionsLine.slots({
               stringKey: capsule + '.by',
+              featuringStringKey: capsule + '.by.featuring',
               chronologyKind: 'album',
             }),
 
diff --git a/src/content/dependencies/generateAlbumTrackListItem.js b/src/content/dependencies/generateAlbumTrackListItem.js
index 7d5d2c6e..851bf32e 100644
--- a/src/content/dependencies/generateAlbumTrackListItem.js
+++ b/src/content/dependencies/generateAlbumTrackListItem.js
@@ -3,7 +3,7 @@ import {compareArrays, empty} from '#sugar';
 export default {
   contentDependencies: [
     'generateAlbumTrackListMissingDuration',
-    'linkContribution',
+    'generateArtistCredit',
     'linkTrack',
   ],
 
@@ -31,11 +31,10 @@ export default {
   relations(relation, query, track) {
     const relations = {};
 
-    if (!empty(track.artistContribs)) {
-      relations.contributionLinks =
-        track.artistContribs
-          .map(contrib => relation('linkContribution', contrib));
-    }
+    relations.credit =
+      relation('generateArtistCredit',
+        track.artistContribs,
+        track.album.artistContribs);
 
     relations.trackLink =
       relation('linkTrack', track);
@@ -113,16 +112,25 @@ export default {
                 : relations.missingDuration);
           }
 
-          if (data.showArtists) {
+          const artistCapsule = language.encapsulate(itemCapsule, 'withArtists');
+
+          relations.credit.setSlots({
+            normalStringKey:
+              artistCapsule + '.by',
+
+            featuringStringKey:
+              artistCapsule + '.featuring',
+
+            normalFeaturingStringKey:
+              artistCapsule + '.by.featuring',
+          });
+
+          if (!html.isBlank(relations.credit)) {
             workingCapsule += '.withArtists';
             workingOptions.by =
               html.tag('span', {class: 'by'},
                 html.metatag('chunkwrap', {split: ','},
-                  html.resolve(
-                    language.$(itemCapsule, 'withArtists.by', {
-                      artists:
-                        language.formatConjunctionList(relations.contributionLinks),
-                    }))));
+                  html.resolve(relations.credit)));
           }
 
           return language.$(workingCapsule, workingOptions);
diff --git a/src/content/dependencies/generateArtistCredit.js b/src/content/dependencies/generateArtistCredit.js
index 51a3bb48..e9af9cc5 100644
--- a/src/content/dependencies/generateArtistCredit.js
+++ b/src/content/dependencies/generateArtistCredit.js
@@ -1,4 +1,4 @@
-import {empty} from '#sugar';
+import {compareArrays, empty} from '#sugar';
 
 export default {
   contentDependencies: [
@@ -8,75 +8,155 @@ export default {
 
   extraDependencies: ['html', 'language'],
 
-  query: (contributions) => ({
-    normalContributions:
-      contributions
-        .filter(contrib => !contrib.annotation?.startsWith(`edits for wiki`)),
+  query: (creditContributions, contextContributions) => {
+    const query = {};
 
-    wikiEditContributions:
-      contributions
-        .filter(contrib => contrib.annotation?.startsWith(`edits for wiki`)),
-  }),
+    const featuringFilter = contribution =>
+      contribution.annotation === 'featuring';
+
+    const wikiEditFilter = contribution =>
+      contribution.annotation?.startsWith('edits for wiki');
+
+    const normalFilter = contribution =>
+      !featuringFilter(contribution) &&
+      !wikiEditFilter(contribution);
+
+    query.normalContributions =
+      creditContributions.filter(normalFilter);
+
+    query.featuringContributions =
+      creditContributions.filter(featuringFilter);
 
-  relations: (relation, query, _contributions) => ({
-    contributionLinks:
+    query.wikiEditContributions =
+      creditContributions.filter(wikiEditFilter);
+
+    const contextNormalContributions =
+      contextContributions.filter(normalFilter);
+
+    query.normalContributionsAreDifferent =
+      !compareArrays(
+        query.normalContributions.map(({artist}) => artist),
+        contextNormalContributions.map(({artist}) => artist),
+        {checkOrder: false});
+
+    return query;
+  },
+
+  relations: (relation, query, _creditContributions, _contextContributions) => ({
+    normalContributionLinks:
       query.normalContributions
         .map(contrib => relation('linkContribution', contrib)),
 
+    featuringContributionLinks:
+      query.featuringContributions
+        .map(contrib => relation('linkContribution', contrib)),
+
     wikiEditsPart:
       relation('generateArtistCreditWikiEditsPart',
         query.wikiEditContributions),
   }),
 
-  data: (query, _contributions) => ({
+  data: (query, _creditContributions, _contextContributions) => ({
+    normalContributionsAreDifferent:
+      query.normalContributionsAreDifferent,
+
     hasWikiEdits:
       !empty(query.wikiEditContributions),
   }),
 
   slots: {
-    showAnnotation: {type: 'boolean', default: true},
-    showExternalLinks: {type: 'boolean', default: true},
-    showChronology: {type: 'boolean', default: true},
+    // This string is mandatory.
+    normalStringKey: {type: 'string'},
+
+    // This string is optional.
+    // Without it, there's no special behavior for "featuring" credits.
+    normalFeaturingStringKey: {type: 'string'},
+
+    // This string is optional.
+    // Without it, "featuring" credits will always be alongside main credits.
+    // It won't be used if contextContributions isn't provided.
+    featuringStringKey: {type: 'string'},
+
+    showAnnotation: {type: 'boolean', default: false},
+    showExternalLinks: {type: 'boolean', default: false},
+    showChronology: {type: 'boolean', default: false},
+    showWikiEdits: {type: 'boolean', default: false},
 
     trimAnnotation: {type: 'boolean', default: false},
 
     chronologyKind: {type: 'string'},
-
-    stringKey: {type: 'string'},
   },
 
-  generate(data, relations, slots, {language}) {
-    const contributionsList =
-      language.formatConjunctionList(
-        relations.contributionLinks.map(link =>
-          link.slots({
-            showAnnotation: slots.showAnnotation,
-            showExternalLinks: slots.showExternalLinks,
-            showChronology: slots.showChronology,
-
-            trimAnnotation: slots.trimAnnotation,
-
-            chronologyKind: slots.chronologyKind,
-          })));
-
-    return language.$(slots.stringKey, {
-      [language.onlyIfOptions]: ['artists'],
-
-      artists:
-        (data.hasWikiEdits
-          ? language.encapsulate('misc.artistLink.withEditsForWiki', capsule =>
-              language.$(capsule, {
-                // It's nonsense to display "+ edits" without
-                // having any regular contributions, also.
-                [language.onlyIfOptions]: ['artists'],
-
-                artists: contributionsList,
-                edits:
-                  relations.wikiEditsPart.slots({
-                    showAnnotation: slots.showAnnotation,
-                  }),
-              }))
-          : contributionsList),
-    });
+  generate(data, relations, slots, {html, language}) {
+    if (!slots.normalStringKey) return html.blank();
+
+    for (const link of [
+      ...relations.normalContributionLinks,
+      ...relations.featuringContributionLinks,
+    ]) {
+      link.setSlots({
+        showExternalLinks: slots.showExternalLinks,
+        showChronology: slots.showChronology,
+        trimAnnotation: slots.trimAnnotation,
+        chronologyKind: slots.chronologyKind,
+      });
+    }
+
+    for (const link of relations.normalContributionLinks) {
+      link.setSlots({
+        showAnnotation: slots.showAnnotation,
+      });
+    }
+
+    for (const link of relations.featuringContributionLinks) {
+      link.setSlots({
+        showAnnotation: false,
+      });
+    }
+
+    if (empty(relations.normalContributionLinks)) {
+      return html.blank();
+    }
+
+    const artistsList =
+      (data.hasWikiEdits && slots.showWikiEdits
+        ? language.$('misc.artistLink.withEditsForWiki', {
+            artists:
+              language.formatConjunctionList(relations.normalContributionLinks),
+
+            edits:
+              relations.wikiEditsPart.slots({
+                showAnnotation: slots.showAnnotation,
+              }),
+          })
+        : language.formatConjunctionList(relations.normalContributionLinks));
+
+    const featuringList =
+      language.formatConjunctionList(relations.featuringContributionLinks);
+
+    const everyoneList =
+      language.formatConjunctionList([
+        ...relations.normalContributionLinks,
+        ...relations.featuringContributionLinks,
+      ]);
+
+    if (empty(relations.featuringContributionLinks)) {
+      if (data.normalContributionsAreDifferent) {
+        return language.$(slots.normalStringKey, {artists: artistsList});
+      } else {
+        return html.blank();
+      }
+    }
+
+    if (data.normalContributionsAreDifferent && slots.normalFeaturingStringKey) {
+      return language.$(slots.normalFeaturingStringKey, {
+        artists: artistsList,
+        featuring: featuringList,
+      });
+    } else if (slots.featuringStringKey) {
+      return language.$(slots.featuringStringKey, {artists: featuringList});
+    } else {
+      return language.$(slots.normalStringKey, {artists: everyoneList});
+    }
   },
 };
diff --git a/src/content/dependencies/generateReleaseInfoContributionsLine.js b/src/content/dependencies/generateReleaseInfoContributionsLine.js
index 30048a78..016e0a2c 100644
--- a/src/content/dependencies/generateReleaseInfoContributionsLine.js
+++ b/src/content/dependencies/generateReleaseInfoContributionsLine.js
@@ -4,11 +4,13 @@ export default {
 
   relations: (relation, contributions) => ({
     credit:
-      relation('generateArtistCredit', contributions),
+      relation('generateArtistCredit', contributions, []),
   }),
 
   slots: {
     stringKey: {type: 'string'},
+    featuringStringKey: {type: 'string'},
+
     chronologyKind: {type: 'string'},
   },
 
@@ -17,11 +19,13 @@ export default {
       showAnnotation: true,
       showExternalLinks: true,
       showChronology: true,
+      showWikiEdits: true,
 
       trimAnnotation: false,
 
-      stringKey: slots.stringKey,
-
       chronologyKind: slots.chronologyKind,
+
+      normalStringKey: slots.stringKey,
+      normalFeaturingStringKey: slots.featuringStringKey,
     }),
 };
diff --git a/src/content/dependencies/generateTrackReleaseInfo.js b/src/content/dependencies/generateTrackReleaseInfo.js
index 8a081046..38b8383f 100644
--- a/src/content/dependencies/generateTrackReleaseInfo.js
+++ b/src/content/dependencies/generateTrackReleaseInfo.js
@@ -56,6 +56,7 @@ export default {
           [
             relations.artistContributionLinks.slots({
               stringKey: capsule + '.by',
+              featuringStringKey: capsule + '.by.featuring',
               chronologyKind: 'track',
             }),