« 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/generateContributionLinks.js23
-rw-r--r--src/content/dependencies/generateIconForURL.js51
-rw-r--r--src/misc-templates.js46
-rw-r--r--test/unit/content/dependencies/generateContributionLinks.js93
4 files changed, 103 insertions, 110 deletions
diff --git a/src/content/dependencies/generateContributionLinks.js b/src/content/dependencies/generateContributionLinks.js
index a79c8234..18bc409d 100644
--- a/src/content/dependencies/generateContributionLinks.js
+++ b/src/content/dependencies/generateContributionLinks.js
@@ -3,37 +3,40 @@ import {empty} from '../../util/sugar.js';
 export default {
   contentDependencies: [
     'linkArtist',
+    'generateIconForURL',
   ],
 
   extraDependencies: [
     'html',
-    'iconifyURL',
     'language',
   ],
 
-  relations(relation, contributions) {
+  relations(relation, contributions, {showIcons = false} = {}) {
     const relations = {};
 
     relations.artistLinks =
       contributions.map(({who}) => relation('linkArtist', who));
 
+    if (showIcons) {
+      relations.artistIcons =
+        contributions.map(({who}) =>
+          who.urls.map(url =>
+            relation('generateIconForURL', url)));
+    }
+
     return relations;
   },
 
   data(contributions, {
     showContribution = false,
     showIcons = false,
-  }) {
+  } = {}) {
     const data = {};
 
-    data.showContribution = showContribution;
-    data.showIcons = showIcons;
-
     data.contributionData =
       contributions.map(({who, what}) => ({
         hasContributionPart: !!(showContribution && what),
         hasExternalPart: !!(showIcons && !empty(who.urls)),
-        artistUrls: who.urls,
         contribution: showContribution && what,
       }));
 
@@ -42,23 +45,21 @@ export default {
 
   generate(data, relations, {
     html,
-    iconifyURL,
     language,
   }) {
     return language.formatConjunctionList(
       data.contributionData.map(({
         hasContributionPart,
         hasExternalPart,
-        artistUrls,
         contribution,
       }, index) => {
         const artistLink = relations.artistLinks[index];
+        const artistIcons = relations.artistIcons?.[index];
 
         const externalLinks = hasExternalPart &&
           html.tag('span',
             {[html.noEdgeWhitespace]: true, class: 'icons'},
-            language.formatUnitList(
-              artistUrls.map(url => iconifyURL(url, {language}))));
+            language.formatUnitList(artistIcons));
 
         return (
           (hasContributionPart
diff --git a/src/content/dependencies/generateIconForURL.js b/src/content/dependencies/generateIconForURL.js
new file mode 100644
index 00000000..4473ccbf
--- /dev/null
+++ b/src/content/dependencies/generateIconForURL.js
@@ -0,0 +1,51 @@
+const BANDCAMP_DOMAINS = [
+  'bc.s3m.us',
+  'music.solatrux.com',
+];
+
+const MASTODON_DOMAINS = [
+  'types.pl',
+];
+
+export default {
+  extraDependencies: ['html', 'language', 'to'],
+
+  data(url) {
+    return {url};
+  },
+
+  generate(data, {html, language, to}) {
+    const domain = new URL(data.url).hostname;
+    const [id, msg] = (
+      domain.includes('bandcamp.com')
+        ? ['bandcamp', language.$('misc.external.bandcamp')]
+      : BANDCAMP_DOMAINS.includes(domain)
+        ? ['bandcamp', language.$('misc.external.bandcamp.domain', {domain})]
+      : MASTODON_DOMAINS.includes(domain)
+        ? ['mastodon', language.$('misc.external.mastodon.domain', {domain})]
+      : domain.includes('youtu')
+        ? ['youtube', language.$('misc.external.youtube')]
+      : domain.includes('soundcloud')
+        ? ['soundcloud', language.$('misc.external.soundcloud')]
+      : domain.includes('tumblr.com')
+        ? ['tumblr', language.$('misc.external.tumblr')]
+      : domain.includes('twitter.com')
+        ? ['twitter', language.$('misc.external.twitter')]
+      : domain.includes('deviantart.com')
+        ? ['deviantart', language.$('misc.external.deviantart')]
+      : domain.includes('instagram.com')
+        ? ['instagram', language.$('misc.external.bandcamp')]
+      : domain.includes('newgrounds.com')
+        ? ['newgrounds', language.$('misc.external.newgrounds')]
+        : ['globe', language.$('misc.external.domain', {domain})]);
+
+    return html.tag('a',
+      {href: data.url, class: 'icon'},
+      html.tag('svg', [
+        html.tag('title', msg),
+        html.tag('use', {
+          href: to('shared.staticFile', `icons.svg#icon-${id}`),
+        }),
+      ]));
+  },
+};
diff --git a/src/misc-templates.js b/src/misc-templates.js
index 11a95c7c..39e62ddf 100644
--- a/src/misc-templates.js
+++ b/src/misc-templates.js
@@ -18,10 +18,6 @@ import {
   sortChronologically,
 } from './util/wiki-data.js';
 
-const BANDCAMP_DOMAINS = ['bc.s3m.us', 'music.solatrux.com'];
-
-const MASTODON_DOMAINS = ['types.pl'];
-
 // "Additional Files" listing
 
 function unbound_generateAdditionalFilesShortcut(additionalFiles, {
@@ -337,48 +333,6 @@ function unbound_fancifyFlashURL(url, flash, {
     : link);
 }
 
-function unbound_iconifyURL(url, {
-  html,
-  language,
-  to,
-}) {
-  const domain = new URL(url).hostname;
-  const [id, msg] = (
-    domain.includes('bandcamp.com')
-      ? ['bandcamp', language.$('misc.external.bandcamp')]
-    : BANDCAMP_DOMAINS.includes(domain)
-      ? ['bandcamp', language.$('misc.external.bandcamp.domain', {domain})]
-    : MASTODON_DOMAINS.includes(domain)
-      ? ['mastodon', language.$('misc.external.mastodon.domain', {domain})]
-    : domain.includes('youtu')
-      ? ['youtube', language.$('misc.external.youtube')]
-    : domain.includes('soundcloud')
-      ? ['soundcloud', language.$('misc.external.soundcloud')]
-    : domain.includes('tumblr.com')
-      ? ['tumblr', language.$('misc.external.tumblr')]
-    : domain.includes('twitter.com')
-      ? ['twitter', language.$('misc.external.twitter')]
-    : domain.includes('deviantart.com')
-      ? ['deviantart', language.$('misc.external.deviantart')]
-    : domain.includes('instagram.com')
-      ? ['instagram', language.$('misc.external.bandcamp')]
-    : domain.includes('newgrounds.com')
-      ? ['newgrounds', language.$('misc.external.newgrounds')]
-      : ['globe', language.$('misc.external.domain', {domain})]);
-
-  return html.tag('a',
-    {
-      href: url,
-      class: 'icon',
-    },
-    html.tag('svg', [
-      html.tag('title', msg),
-      html.tag('use', {
-        href: to('shared.staticFile', `icons.svg#icon-${id}`),
-      }),
-    ]));
-}
-
 // Grids
 
 function unbound_getGridHTML({
diff --git a/test/unit/content/dependencies/generateContributionLinks.js b/test/unit/content/dependencies/generateContributionLinks.js
index a0bb64ec..5ed8f782 100644
--- a/test/unit/content/dependencies/generateContributionLinks.js
+++ b/test/unit/content/dependencies/generateContributionLinks.js
@@ -2,28 +2,28 @@ import t from 'tap';
 import {testContentFunctions} from '../../../lib/content-function.js';
 
 t.test('generateContributionLinks (unit)', async t => {
-  await testContentFunctions(t, 'generateContributionLinks (unit 1)', async (t, evaluate) => {
-    const artist1 = {
-      name: 'Clark Powell',
-      urls: ['https://soundcloud.com/plazmataz'],
-    };
-
-    const artist2 = {
-      name: 'Grounder & Scratch',
-      urls: [],
-    };
-
-    const artist3 = {
-      name: 'Toby Fox',
-      urls: ['https://tobyfox.bandcamp.com/', 'https://toby.fox/'],
-    };
-
-    const contributions = [
-      {who: artist1, what: null},
-      {who: artist2, what: 'Snooping'},
-      {who: artist3, what: 'Arrangement'},
-    ];
+  const artist1 = {
+    name: 'Clark Powell',
+    urls: ['https://soundcloud.com/plazmataz'],
+  };
+
+  const artist2 = {
+    name: 'Grounder & Scratch',
+    urls: [],
+  };
+
+  const artist3 = {
+    name: 'Toby Fox',
+    urls: ['https://tobyfox.bandcamp.com/', 'https://toby.fox/'],
+  };
+
+  const contributions = [
+    {who: artist1, what: null},
+    {who: artist2, what: 'Snooping'},
+    {who: artist3, what: 'Arrangement'},
+  ];
 
+  await testContentFunctions(t, 'generateContributionLinks (unit 1)', async (t, evaluate) => {
     const config = {
       showContribution: true,
       showIcons: true,
@@ -44,46 +44,29 @@ t.test('generateContributionLinks (unit)', async t => {
 
           // This can be tweaked to return a specific (mocked) template
           // for each artist if we need to test for slots in the future.
-          generate: mock.function(() => 'artist link')
+          generate: mock.function('linkArtist.generate', () => 'artist link')
             .repeat(3),
         },
+
+        generateIconForURL: {
+          data: mock.function('generateIconForURL.data', () => ({}))
+            .args([artist1.urls[0]]).next()
+            .args([artist3.urls[0]]).next()
+            .args([artist3.urls[1]]),
+
+          generate: mock.function('generateIconForURL.generate', () => 'icon')
+            .repeat(3),
+        }
       })),
     });
 
     evaluate({
       name: 'generateContributionLinks',
       args: [contributions, config],
-      extraDependencies: evaluate.mock(mock => ({
-        iconifyURL: mock.function(() => 'icon')
-          .args([artist1.urls[0], undefined]).next()
-          .args([artist3.urls[0], undefined]).next()
-          .args([artist3.urls[1], undefined]),
-      })),
     });
   });
 
   await testContentFunctions(t, 'generateContributionLinks (unit 2)', async (t, evaluate) => {
-    const artist1 = {
-      name: 'Clark Powell',
-      urls: ['https://soundcloud.com/plazmataz'],
-    };
-
-    const artist2 = {
-      name: 'Grounder & Scratch',
-      urls: [],
-    };
-
-    const artist3 = {
-      name: 'Toby Fox',
-      urls: ['https://tobyfox.bandcamp.com/', 'https://toby.fox/'],
-    };
-
-    const contributions = [
-      {who: artist1, what: null},
-      {who: artist2, what: 'Snooping'},
-      {who: artist3, what: 'Arrangement'},
-    ];
-
     const config = {
       showContribution: false,
       showIcons: false,
@@ -105,16 +88,20 @@ t.test('generateContributionLinks (unit)', async t => {
           generate: mock.function(() => 'artist link')
             .repeat(3),
         },
+
+        generateIconForURL: {
+          data: mock.function('generateIconForURL.data', () => ({}))
+            .neverCalled(),
+
+          generate: mock.function('generateIconForURL.generate', () => 'icon')
+            .neverCalled(),
+        },
       })),
     });
 
     evaluate({
       name: 'generateContributionLinks',
       args: [contributions, config],
-      extraDependencies: evaluate.mock(mock => ({
-        iconifyURL: mock.function(() => 'icon')
-          .neverCalled(),
-      })),
     });
   });
 });