« get me outta code hell

data: annotated artwork references - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2024-11-14 07:37:14 -0400
committer(quasar) nebula <qznebula@protonmail.com>2024-11-14 07:37:14 -0400
commit913f418eadb0b085c805ff1c83b749a0ce620741 (patch)
tree6d369056d724552ac5191930ae87c05b93ee64fc /src
parentdb0fd78ca60fc695f87d1f3adf53967bdae2796f (diff)
data: annotated artwork references
Not used on-site, but this is all coded internally.
Diffstat (limited to 'src')
-rw-r--r--src/data/checks.js16
-rw-r--r--src/data/composite/wiki-data/index.js1
-rw-r--r--src/data/composite/wiki-data/withResolvedArtworkReferenceList.js125
-rw-r--r--src/data/composite/wiki-properties/index.js1
-rw-r--r--src/data/composite/wiki-properties/referencedArtworkList.js47
-rw-r--r--src/data/things/album.js17
-rw-r--r--src/data/things/track.js17
-rw-r--r--src/data/validators.js11
-rw-r--r--src/data/yaml.js25
9 files changed, 248 insertions, 12 deletions
diff --git a/src/data/checks.js b/src/data/checks.js
index da7b228c..8c8e7a5d 100644
--- a/src/data/checks.js
+++ b/src/data/checks.js
@@ -183,8 +183,8 @@ export function filterReferenceErrors(wikiData, {
       bannerArtistContribs: '_contrib',
       groups: 'group',
       artTags: '_artTag',
-      referencedTrackArtworks: 'track',
-      referencedAlbumArtworks: 'album',
+      referencedTrackArtworks: '_trackArtwork',
+      referencedAlbumArtworks: '_albumArtwork',
       commentary: '_commentary',
     }],
 
@@ -221,8 +221,8 @@ export function filterReferenceErrors(wikiData, {
       referencedTracks: '_trackNotRerelease',
       sampledTracks: '_trackNotRerelease',
       artTags: '_artTag',
-      referencedTrackArtworks: 'track',
-      referencedAlbumArtworks: 'album',
+      referencedTrackArtworks: '_trackArtwork',
+      referencedAlbumArtworks: '_albumArtwork',
       originalReleaseTrack: '_trackNotRerelease',
       commentary: '_commentary',
     }],
@@ -289,6 +289,10 @@ export function filterReferenceErrors(wikiData, {
             let findFn;
 
             switch (findFnKey) {
+              case '_albumArtwork':
+                findFn = ref => boundFind.album(ref.reference);
+                break;
+
               case '_artTag':
                 findFn = boundFind.artTag;
                 break;
@@ -315,6 +319,10 @@ export function filterReferenceErrors(wikiData, {
                 findFn = boundFind.album;
                 break;
 
+              case '_trackArtwork':
+                findFn = ref => boundFind.track(ref.reference);
+                break;
+
               case '_trackNotRerelease':
                 findFn = trackRef => {
                   const track = boundFind.track(trackRef);
diff --git a/src/data/composite/wiki-data/index.js b/src/data/composite/wiki-data/index.js
index afd8bdd2..451aa266 100644
--- a/src/data/composite/wiki-data/index.js
+++ b/src/data/composite/wiki-data/index.js
@@ -14,6 +14,7 @@ export {default as withDirectoryFromName} from './withDirectoryFromName.js';
 export {default as withParsedCommentaryEntries} from './withParsedCommentaryEntries.js';
 export {default as withRecontextualizedContributionList} from './withRecontextualizedContributionList.js';
 export {default as withRedatedContributionList} from './withRedatedContributionList.js';
+export {default as withResolvedArtworkReferenceList} from './withResolvedArtworkReferenceList.js';
 export {default as withResolvedContribs} from './withResolvedContribs.js';
 export {default as withResolvedReference} from './withResolvedReference.js';
 export {default as withResolvedReferenceList} from './withResolvedReferenceList.js';
diff --git a/src/data/composite/wiki-data/withResolvedArtworkReferenceList.js b/src/data/composite/wiki-data/withResolvedArtworkReferenceList.js
new file mode 100644
index 00000000..e9c6a590
--- /dev/null
+++ b/src/data/composite/wiki-data/withResolvedArtworkReferenceList.js
@@ -0,0 +1,125 @@
+import {input, templateCompositeFrom} from '#composite';
+import {stitchArrays} from '#sugar';
+import {is, isString, optional, validateArrayItems, validateProperties}
+  from '#validators';
+
+import {withFilteredList, withMappedList, withPropertiesFromList}
+  from '#composite/data';
+
+import inputWikiData from './inputWikiData.js';
+import withResolvedReferenceList from './withResolvedReferenceList.js';
+
+export default templateCompositeFrom({
+  annotation: `withResolvedArtworkReferenceList`,
+
+  inputs: {
+    list: input({
+      validate:
+        validateArrayItems(
+          validateProperties({
+            reference: isString,
+            annotation: optional(isString),
+          })),
+
+      acceptsNull: true,
+    }),
+
+    data: inputWikiData({allowMixedTypes: false}),
+    find: input({type: 'function'}),
+
+    notFoundMode: input({
+      validate: is('exit', 'filter', 'null'),
+      defaultValue: 'filter',
+    }),
+  },
+
+  steps: () => [
+    withPropertiesFromList({
+      list: input('list'),
+      properties: input.value([
+        'reference',
+        'annotation',
+      ]),
+    }),
+
+    withResolvedReferenceList({
+      list: '#list.reference',
+      data: input('data'),
+      find: input('find'),
+      notFoundMode: input.value('null'),
+    }),
+
+    {
+      dependencies: [
+        '#resolvedReferenceList',
+        '#list.annotation',
+      ],
+
+      compute: (continuation, {
+        ['#resolvedReferenceList']: thing,
+        ['#list.annotation']: annotation,
+      }) => continuation({
+        ['#matches']:
+          stitchArrays({
+            thing,
+            annotation,
+          }),
+      }),
+    },
+
+    {
+      dependencies: ['#matches'],
+      compute: (continuation, {'#matches': matches}) =>
+        (matches.every(match => match)
+          ? continuation.raiseOutput({
+              ['#resolvedArtworkReferenceList']:
+                matches,
+            })
+          : continuation()),
+    },
+
+    {
+      dependencies: [input('notFoundMode')],
+      compute: (continuation, {
+        [input('notFoundMode')]: notFoundMode,
+      }) =>
+        (notFoundMode === 'exit'
+          ? continuation.exit([])
+          : continuation()),
+    },
+
+    {
+      dependencies: ['#matches', input('notFoundMode')],
+      compute: (continuation, {
+        ['#matches']: matches,
+        [input('notFoundMode')]: notFoundMode,
+      }) =>
+        (notFoundMode === 'null'
+          ? continuation.raiseOutput({
+              ['#resolvedArtworkReferenceList']:
+                matches,
+            })
+          : continuation()),
+    },
+
+    withMappedList({
+      list: '#resolvedReferenceList',
+      map: input.value(thing => thing !== null),
+    }),
+
+    withFilteredList({
+      list: '#matches',
+      filter: '#mappedList',
+    }),
+
+    {
+      dependencies: ['#filteredList'],
+      compute: (continuation, {
+        ['#filteredList']: filteredList,
+      }) => continuation({
+        ['#resolvedArtworkReferenceList']:
+          filteredList,
+      }),
+    },
+  ],
+})
diff --git a/src/data/composite/wiki-properties/index.js b/src/data/composite/wiki-properties/index.js
index 32916771..d39bff3a 100644
--- a/src/data/composite/wiki-properties/index.js
+++ b/src/data/composite/wiki-properties/index.js
@@ -19,6 +19,7 @@ export {default as fileExtension} from './fileExtension.js';
 export {default as flag} from './flag.js';
 export {default as name} from './name.js';
 export {default as referenceList} from './referenceList.js';
+export {default as referencedArtworkList} from './referencedArtworkList.js';
 export {default as reverseContributionList} from './reverseContributionList.js';
 export {default as reverseReferenceList} from './reverseReferenceList.js';
 export {default as reverseSingleReferenceList} from './reverseSingleReferenceList.js';
diff --git a/src/data/composite/wiki-properties/referencedArtworkList.js b/src/data/composite/wiki-properties/referencedArtworkList.js
new file mode 100644
index 00000000..bd2962de
--- /dev/null
+++ b/src/data/composite/wiki-properties/referencedArtworkList.js
@@ -0,0 +1,47 @@
+import {input, templateCompositeFrom} from '#composite';
+import {isThingClass, validateAnnotatedReferenceList} from '#validators';
+
+import {exposeDependency} from '#composite/control-flow';
+import {inputWikiData, withResolvedArtworkReferenceList} from '#composite/wiki-data';
+
+export default templateCompositeFrom({
+  annotation: `referencedArtworkList`,
+
+  inputs: {
+    class: input.staticValue({
+      validate: isThingClass,
+      acceptsNull: true,
+      defaultValue: null,
+    }),
+
+    referenceType: input.staticValue({
+      type: 'string',
+      acceptsNull: true,
+      defaultValue: null,
+    }),
+
+    data: inputWikiData({allowMixedTypes: false}),
+    find: input({type: 'function'}),
+  },
+
+  update: ({
+    [input.staticValue('class')]: thingClass,
+    [input.staticValue('referenceType')]: referenceType,
+  }) => ({
+    validate:
+      validateAnnotatedReferenceList(
+        (thingClass
+          ? thingClass[Symbol.for('Thing.referenceType')]
+          : referenceType)),
+  }),
+
+  steps: () => [
+    withResolvedArtworkReferenceList({
+      list: input.updateValue(),
+      data: input('data'),
+      find: input('find'),
+    }),
+
+    exposeDependency({dependency: '#resolvedArtworkReferenceList'}),
+  ],
+});
diff --git a/src/data/things/album.js b/src/data/things/album.js
index 539f4fb1..b8009063 100644
--- a/src/data/things/album.js
+++ b/src/data/things/album.js
@@ -19,6 +19,7 @@ import {
   parseContributors,
   parseDate,
   parseDimensions,
+  parseReferencedArtworks,
 } from '#yaml';
 
 import {exitWithoutDependency, exposeDependency, exposeUpdateValueOrContinue}
@@ -46,6 +47,7 @@ import {
   fileExtension,
   flag,
   name,
+  referencedArtworkList,
   referenceList,
   simpleDate,
   simpleString,
@@ -223,7 +225,7 @@ export class Album extends Thing {
         value: input.value([]),
       }),
 
-      referenceList({
+      referencedArtworkList({
         class: input.value(Track),
         find: input.value(find.track),
         data: 'trackData',
@@ -236,7 +238,7 @@ export class Album extends Thing {
         value: input.value([]),
       }),
 
-      referenceList({
+      referencedArtworkList({
         class: input.value(Album),
         find: input.value(find.album),
         data: 'albumData',
@@ -410,8 +412,15 @@ export class Album extends Thing {
         transform: parseAdditionalFiles,
       },
 
-      'Referenced Track Artworks': {property: 'referencedTrackArtworks'},
-      'Referenced Album Artworks': {property: 'referencedAlbumArtworks'},
+      'Referenced Track Artworks': {
+        property: 'referencedTrackArtworks',
+        transform: parseReferencedArtworks,
+      },
+
+      'Referenced Album Artworks': {
+        property: 'referencedAlbumArtworks',
+        transform: parseReferencedArtworks,
+      },
 
       'Franchises': {ignore: true},
 
diff --git a/src/data/things/track.js b/src/data/things/track.js
index 586e5f4c..078ad11b 100644
--- a/src/data/things/track.js
+++ b/src/data/things/track.js
@@ -15,6 +15,7 @@ import {
   parseDate,
   parseDimensions,
   parseDuration,
+  parseReferencedArtworks,
 } from '#yaml';
 
 import {withPropertyFromObject} from '#composite/data';
@@ -47,6 +48,7 @@ import {
   flag,
   name,
   referenceList,
+  referencedArtworkList,
   reverseReferenceList,
   simpleDate,
   simpleString,
@@ -324,7 +326,7 @@ export class Track extends Thing {
         value: input.value([]),
       }),
 
-      referenceList({
+      referencedArtworkList({
         class: input.value(Track),
         find: input.value(find.track),
         data: 'trackData',
@@ -336,7 +338,7 @@ export class Track extends Thing {
         value: input.value([]),
       }),
 
-      referenceList({
+      referencedArtworkList({
         class: input.value(Album),
         find: input.value(find.album),
         data: 'albumData',
@@ -506,8 +508,15 @@ export class Track extends Thing {
       'Referenced Tracks': {property: 'referencedTracks'},
       'Sampled Tracks': {property: 'sampledTracks'},
 
-      'Referenced Track Artworks': {property: 'referencedTrackArtworks'},
-      'Referenced Album Artworks': {property: 'referencedAlbumArtworks'},
+      'Referenced Track Artworks': {
+        property: 'referencedTrackArtworks',
+        transform: parseReferencedArtworks,
+      },
+
+      'Referenced Album Artworks': {
+        property: 'referencedAlbumArtworks',
+        transform: parseReferencedArtworks,
+      },
 
       'Franchises': {ignore: true},
       'Inherit Franchises': {ignore: true},
diff --git a/src/data/validators.js b/src/data/validators.js
index 39559cfa..f886c4f2 100644
--- a/src/data/validators.js
+++ b/src/data/validators.js
@@ -819,6 +819,17 @@ export function validateReferenceList(type = '') {
   return validateArrayItems(validateReference(type));
 }
 
+export function validateAnnotatedReference(type = '') {
+  return validateProperties({
+    reference: validateReference(type),
+    annotation: optional(isContentString),
+  });
+}
+
+export function validateAnnotatedReferenceList(type = '') {
+  return validateArrayItems(validateAnnotatedReference(type));
+}
+
 export function validateThing({
   referenceType: expectedReferenceType = '',
 } = {}) {
diff --git a/src/data/yaml.js b/src/data/yaml.js
index 3f79aa65..725f4f3a 100644
--- a/src/data/yaml.js
+++ b/src/data/yaml.js
@@ -569,6 +569,31 @@ export function parseContributionPresets(list) {
   });
 }
 
+export function parseReferencedArtworks(entries) {
+  return parseArrayEntries(entries, item => {
+    if (typeof item === 'object' && item['References'])
+      return {
+        reference: item['References'],
+        annotation: item['Annotation'] ?? null,
+      };
+
+    if (typeof item !== 'string') return item;
+
+    const match = item.match(extractAccentRegex);
+    if (!match) {
+      return {
+        reference: item,
+        annotation: null,
+      }
+    }
+
+    return {
+      reference: match.groups.main,
+      annotation: match.groups.accent,
+    };
+  });
+}
+
 // documentModes: Symbols indicating sets of behavior for loading and processing
 // data files.
 export const documentModes = {