« 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/dependencies/generateArtistCredit.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/content/dependencies/generateArtistCredit.js')
-rw-r--r--src/content/dependencies/generateArtistCredit.js194
1 files changed, 194 insertions, 0 deletions
diff --git a/src/content/dependencies/generateArtistCredit.js b/src/content/dependencies/generateArtistCredit.js
new file mode 100644
index 00000000..bab32f7d
--- /dev/null
+++ b/src/content/dependencies/generateArtistCredit.js
@@ -0,0 +1,194 @@
+import {compareArrays, empty} from '#sugar';
+
+export default {
+  contentDependencies: [
+    'generateArtistCreditWikiEditsPart',
+    'linkContribution',
+  ],
+
+  extraDependencies: ['html', 'language'],
+
+  query: (creditContributions, contextContributions) => {
+    const query = {};
+
+    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);
+
+    query.wikiEditContributions =
+      creditContributions.filter(wikiEditFilter);
+
+    const contextNormalContributions =
+      contextContributions.filter(normalFilter);
+
+    // Note that the normal contributions will implicitly *always*
+    // "differ from context" if no context contributions are given,
+    // as in release info lines.
+
+    query.normalContributionArtistsDifferFromContext =
+      !compareArrays(
+        query.normalContributions.map(({artist}) => artist),
+        contextNormalContributions.map(({artist}) => artist),
+        {checkOrder: true});
+
+    query.normalContributionAnnotationsDifferFromContext =
+      !compareArrays(
+        query.normalContributions.map(({annotation}) => annotation),
+        contextNormalContributions.map(({annotation}) => annotation),
+        {checkOrder: true});
+
+    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, _creditContributions, _contextContributions) => ({
+    normalContributionArtistsDifferFromContext:
+      query.normalContributionArtistsDifferFromContext,
+
+    normalContributionAnnotationsDifferFromContext:
+      query.normalContributionAnnotationsDifferFromContext,
+
+    hasWikiEdits:
+      !empty(query.wikiEditContributions),
+  }),
+
+  slots: {
+    // 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'},
+
+    additionalStringOptions: {validate: v => v.isObject},
+
+    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'},
+  },
+
+  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:
+          (slots.featuringStringKey || slots.normalFeaturingStringKey
+            ? false
+            : slots.showAnnotation),
+      });
+    }
+
+    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,
+      ]);
+
+    const effectivelyDiffers =
+      (slots.showAnnotation && data.normalContributionAnnotationsDifferFromContext) ||
+      (data.normalContributionArtistsDifferFromContext);
+
+    if (empty(relations.featuringContributionLinks)) {
+      if (effectivelyDiffers) {
+        return language.$(slots.normalStringKey, {
+          ...slots.additionalStringOptions,
+          artists: artistsList,
+        });
+      } else {
+        return html.blank();
+      }
+    }
+
+    if (effectivelyDiffers && slots.normalFeaturingStringKey) {
+      return language.$(slots.normalFeaturingStringKey, {
+        ...slots.additionalStringOptions,
+        artists: artistsList,
+        featuring: featuringList,
+      });
+    } else if (slots.featuringStringKey) {
+      return language.$(slots.featuringStringKey, {
+        ...slots.additionalStringOptions,
+        artists: featuringList,
+      });
+    } else {
+      return language.$(slots.normalStringKey, {
+        ...slots.additionalStringOptions,
+        artists: everyoneList,
+      });
+    }
+  },
+};