« get me outta code hell

data, yaml, content: support multiple artists per commentary entry - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-11-17 06:53:34 -0400
committer(quasar) nebula <qznebula@protonmail.com>2023-11-17 06:53:34 -0400
commita34b8d027866fbe858a4d2ff3543bc84c9d5983a (patch)
tree39ffd1c8736a5c0483f17e4480f87f05faf67eb1
parentfbcfb88ea407ab76d278c28f1f0711502ab2fbf9 (diff)
data, yaml, content: support multiple artists per commentary entry
-rw-r--r--src/content/dependencies/generateCommentaryEntry.js13
-rw-r--r--src/data/composite/wiki-data/withParsedCommentaryEntries.js41
-rw-r--r--src/data/composite/wiki-properties/commentatorArtists.js23
-rw-r--r--src/data/yaml.js24
-rw-r--r--src/util/wiki-data.js2
5 files changed, 75 insertions, 28 deletions
diff --git a/src/content/dependencies/generateCommentaryEntry.js b/src/content/dependencies/generateCommentaryEntry.js
index b265ed41..0b2b2558 100644
--- a/src/content/dependencies/generateCommentaryEntry.js
+++ b/src/content/dependencies/generateCommentaryEntry.js
@@ -1,3 +1,5 @@
+import {empty} from '#sugar';
+
 export default {
   contentDependencies: [
     'generateColorStyleVariables',
@@ -8,9 +10,10 @@ export default {
   extraDependencies: ['html', 'language'],
 
   relations: (relation, entry) => ({
-    artistLink:
-      (entry.artist && !entry.artistDisplayText
-        ? relation('linkArtist', entry.artist)
+    artistLinks:
+      (!empty(entry.artists) && !entry.artistDisplayText
+        ? entry.artists
+            .map(artist => relation('linkArtist', artist))
         : null),
 
     artistsContent:
@@ -45,8 +48,8 @@ export default {
       html.tag('span', {class: 'commentary-entry-artists'},
         (relations.artistsContent
           ? relations.artistsContent.slot('mode', 'inline')
-       : relations.artistLink
-          ? relations.artistLink
+       : relations.artistLinks
+          ? language.formatConjunctionList(relations.artistLinks)
           : language.$('misc.artistCommentary.entry.title.noArtists')));
 
     const accentParts = ['misc.artistCommentary.entry.title.accent'];
diff --git a/src/data/composite/wiki-data/withParsedCommentaryEntries.js b/src/data/composite/wiki-data/withParsedCommentaryEntries.js
index 7b1c9484..25c07a37 100644
--- a/src/data/composite/wiki-data/withParsedCommentaryEntries.js
+++ b/src/data/composite/wiki-data/withParsedCommentaryEntries.js
@@ -4,7 +4,12 @@ import {stitchArrays} from '#sugar';
 import {isCommentary} from '#validators';
 import {commentaryRegex} from '#wiki-data';
 
-import {fillMissingListItems, withPropertiesFromList} from '#composite/data';
+import {
+  fillMissingListItems,
+  withFlattenedList,
+  withPropertiesFromList,
+  withUnflattenedList,
+} from '#composite/data';
 
 import withResolvedReferenceList from './withResolvedReferenceList.js';
 
@@ -86,23 +91,43 @@ export default templateCompositeFrom({
       list: '#rawMatches.groups',
       prefix: input.value('#entries'),
       properties: input.value([
-        'artistReference',
+        'artistReferences',
         'artistDisplayText',
         'annotation',
         'date',
       ]),
     }),
 
-    // The artistReference group will always have a value, since it's required
+    // The artistReferences group will always have a value, since it's required
     // for the line to match in the first place.
 
+    {
+      dependencies: ['#entries.artistReferences'],
+      compute: (continuation, {
+        ['#entries.artistReferences']: artistReferenceTexts,
+      }) => continuation({
+        ['#entries.artistReferences']:
+          artistReferenceTexts
+            .map(text => text.split(',').map(ref => ref.trim())),
+      }),
+    },
+
+    withFlattenedList({
+      list: '#entries.artistReferences',
+    }),
+
     withResolvedReferenceList({
-      list: '#entries.artistReference',
+      list: '#flattenedList',
       data: 'artistData',
       find: input.value(find.artist),
       notFoundMode: input.value('null'),
+    }),
+
+    withUnflattenedList({
+      list: '#resolvedReferenceList',
+      filter: input.value(false),
     }).outputs({
-      '#resolvedReferenceList': '#entries.artist',
+      '#unflattenedList': '#entries.artists',
     }),
 
     fillMissingListItems({
@@ -127,7 +152,7 @@ export default templateCompositeFrom({
 
     {
       dependencies: [
-        '#entries.artist',
+        '#entries.artists',
         '#entries.artistDisplayText',
         '#entries.annotation',
         '#entries.date',
@@ -135,7 +160,7 @@ export default templateCompositeFrom({
       ],
 
       compute: (continuation, {
-        ['#entries.artist']: artist,
+        ['#entries.artists']: artists,
         ['#entries.artistDisplayText']: artistDisplayText,
         ['#entries.annotation']: annotation,
         ['#entries.date']: date,
@@ -143,7 +168,7 @@ export default templateCompositeFrom({
       }) => continuation({
         ['#parsedCommentaryEntries']:
           stitchArrays({
-            artist,
+            artists,
             artistDisplayText,
             annotation,
             date,
diff --git a/src/data/composite/wiki-properties/commentatorArtists.js b/src/data/composite/wiki-properties/commentatorArtists.js
index 8720e66d..65ab1466 100644
--- a/src/data/composite/wiki-properties/commentatorArtists.js
+++ b/src/data/composite/wiki-properties/commentatorArtists.js
@@ -4,8 +4,9 @@
 import {input, templateCompositeFrom} from '#composite';
 import {unique} from '#sugar';
 
-import {exitWithoutDependency} from '#composite/control-flow';
-import {withPropertyFromList} from '#composite/data';
+import {exitWithoutDependency, exposeDependency}
+  from '#composite/control-flow';
+import {withFlattenedList, withPropertyFromList} from '#composite/data';
 import {withParsedCommentaryEntries} from '#composite/wiki-data';
 
 export default templateCompositeFrom({
@@ -26,15 +27,19 @@ export default templateCompositeFrom({
 
     withPropertyFromList({
       list: '#parsedCommentaryEntries',
-      property: input.value('artist'),
+      property: input.value('artists'),
     }).outputs({
-      '#parsedCommentaryEntries.artist': '#artists',
+      '#parsedCommentaryEntries.artists': '#artistLists',
     }),
 
-    {
-      dependencies: ['#artists'],
-      compute: ({'#artists': artists}) =>
-        unique(artists.filter(artist => artist !== null)),
-    },
+    withFlattenedList({
+      list: '#artistLists',
+    }).outputs({
+      '#flattenedList': '#artists',
+    }),
+
+    exposeDependency({
+      dependency: '#artists',
+    }),
   ],
 });
diff --git a/src/data/yaml.js b/src/data/yaml.js
index 843e70b3..0734d539 100644
--- a/src/data/yaml.js
+++ b/src/data/yaml.js
@@ -21,6 +21,7 @@ import {
   decorateErrorWithIndex,
   decorateErrorWithAnnotation,
   empty,
+  filterAggregate,
   filterProperties,
   openAggregate,
   showAggregate,
@@ -1686,8 +1687,10 @@ export function filterReferenceErrors(wikiData) {
                 if (value) {
                   value =
                     Array.from(value.matchAll(commentaryRegex))
-                      .map(({groups}) => groups.artistReference);
+                      .map(({groups}) => groups.artistReferences)
+                      .map(text => text.split(',').map(text => text.trim()));
                 }
+
                 writeProperty = false;
                 break;
             }
@@ -1804,11 +1807,22 @@ export function filterReferenceErrors(wikiData) {
 
             let newPropertyValue = value;
 
-            if (Array.isArray(value)) {
+            if (findFnKey === '_commentary') {
+              // Commentary doesn't write a property value, so no need to set.
+              filter(
+                value, {message: errorMessage},
+                decorateErrorWithIndex(refs =>
+                  (refs.length === 1
+                    ? suppress(findFn)(refs[0])
+                    : filterAggregate(
+                        refs, {message: `Errors in entry's artist references`},
+                        decorateErrorWithIndex(suppress(findFn)))
+                          .aggregate
+                          .close())));
+            } else if (Array.isArray(value)) {
               newPropertyValue = filter(
-                value,
-                decorateErrorWithIndex(suppress(findFn)),
-                {message: errorMessage});
+                value, {message: errorMessage},
+                decorateErrorWithIndex(suppress(findFn)));
             } else {
               nest({message: errorMessage},
                 suppress(({call}) => {
diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js
index 75a141d3..4c7ec043 100644
--- a/src/util/wiki-data.js
+++ b/src/util/wiki-data.js
@@ -652,7 +652,7 @@ export function sortFlashesChronologically(data, {
 // out of the original string based on the indices matched using this.
 //
 export const commentaryRegex =
-  /^<i>(?<artistReference>.+?)(?:\|(?<artistDisplayText>.+))?:<\/i>(?: \((?<annotation>(?:.*?(?=[,)]))*?)(?:,? ?(?<date>[a-zA-Z]+ [0-9]{1,2}, [0-9]{4,4}|[0-9]{1,2} [^,]*[0-9]{4,4}|[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{2,4}))?\))?/gm;
+  /^<i>(?<artistReferences>.+?)(?:\|(?<artistDisplayText>.+))?:<\/i>(?: \((?<annotation>(?:.*?(?=[,)]))*?)(?:,? ?(?<date>[a-zA-Z]+ [0-9]{1,2}, [0-9]{4,4}|[0-9]{1,2} [^,]*[0-9]{4,4}|[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{2,4}))?\))?/gm;
 
 export function filterAlbumsByCommentary(albums) {
   return albums