« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/data/composite/things/track/withDirectorySuffixes.js113
-rw-r--r--src/data/things/Track.js39
-rw-r--r--src/data/things/album/TrackSection.js46
3 files changed, 157 insertions, 41 deletions
diff --git a/src/data/composite/things/track/withDirectorySuffixes.js b/src/data/composite/things/track/withDirectorySuffixes.js
index efc66f13..be66b5c9 100644
--- a/src/data/composite/things/track/withDirectorySuffixes.js
+++ b/src/data/composite/things/track/withDirectorySuffixes.js
@@ -22,13 +22,23 @@ export default templateCompositeFrom({
       properties: input.value([
         'suffixTrackDirectoriesByDefault',
         'directorySuffixForTracks',
+        'nameDetailForTracks',
+      ]),
+    }),
+
+    withPropertiesFromObject({
+      object: 'album',
+      properties: input.value([
+        'suffixTrackDirectoriesByDefault',
+        'directorySuffixForTracks',
+        'nameDetailForTracks',
       ]),
     }),
 
     {
       dependencies: [
         input('from'),
-        '#trackSection.suffixTrackDirectoriesByDefault',
+        '#album.directorySuffixForTracks',
         '#trackSection.directorySuffixForTracks',
       ],
 
@@ -36,25 +46,34 @@ export default templateCompositeFrom({
         [input('from')]:
           suffixDirectory,
 
-        ['#trackSection.suffixTrackDirectoriesByDefault']:
-          suffixTrackDirectoriesByDefault,
+        ['#album.directorySuffixForTracks']:
+          albumDirectorySuffixForTracks,
 
         ['#trackSection.directorySuffixForTracks']:
-          directorySuffixForTracks,
+          trackSectionDirectorySuffixForTracks,
       }) {
         // All conditions in this chunk process explicitly set values for
-        // the actual update value - that is, everything EXCEPT true or null,
-        // which both pass through to conditional "defaults".
-        // (True and null aren't quite equal, but the difference only matters
-        //  at the very end.)
+        // the actual update value - that is, everything EXCEPT null,
+        // which passes through to conditional "defaults".
 
+        // Note that 'Suffix Directory: true' is literally equivalent to
+        // suffixDirectory = 'album', via yaml transformation.
         if (suffixDirectory === 'album') {
           return continuation.raiseOutput({
-            ['#directorySuffix']: directorySuffixForTracks,
+            ['#directorySuffix']: albumDirectorySuffixForTracks,
             ['#directorySuffixWithinAlbum']: null,
           });
         }
 
+        if (suffixDirectory === 'section') {
+          // Bear in mind the directory is suffixed within the album.
+          // This is repeated in following steps, too.
+          return continuation.raiseOutput({
+            ['#directorySuffix']: trackSectionDirectorySuffixForTracks,
+            ['#directorySuffixWithinAlbum']: trackSectionDirectorySuffixForTracks,
+          });
+        }
+
         if (typeof suffixDirectory === 'string') {
           return continuation.raiseOutput({
             ['#directorySuffix']: suffixDirectory,
@@ -74,7 +93,9 @@ export default templateCompositeFrom({
             suffixDirectory
               .map(item =>
                 (item === 'album'
-                  ? directorySuffixForTracks
+                  ? albumDirectorySuffixForTracks
+               : item === 'section'
+                  ? trackSectionDirectorySuffixForTracks
                   : item));
 
           const parts2 =
@@ -82,6 +103,8 @@ export default templateCompositeFrom({
               .map(item =>
                 (item === 'album'
                   ? null
+               : item === 'section'
+                  ? trackSectionDirectorySuffixForTracks
                   : item))
               .filter(Boolean);
 
@@ -91,27 +114,53 @@ export default templateCompositeFrom({
           });
         }
 
-        // It's true or null - just continue.
+        // It's null - just continue.
         return continuation();
       },
     },
 
     {
+      // Neither of the track section fields inherit from the album.
+      // Importantly, trackSection.suffixTrackDirectoriesByDefault can be null
+      // OR false at the same time as album.suffixTrackDirectoriesByDefault
+      // is true, and those carry different meanings.
       dependencies: [
         '#trackSection.suffixTrackDirectoriesByDefault',
         '#trackSection.directorySuffixForTracks',
+        '#album.suffixTrackDirectoriesByDefault',
+        '#album.directorySuffixForTracks',
       ],
 
       compute(continuation, {
         ['#trackSection.suffixTrackDirectoriesByDefault']:
-          suffixTrackDirectoriesByDefault,
+          trackSectionSuffixTrackDirectoriesByDefault,
 
         ['#trackSection.directorySuffixForTracks']:
-          directorySuffixForTracks,
+          trackSectionDirectorySuffixForTracks,
+
+        ['#album.suffixTrackDirectoriesByDefault']:
+          albumSuffixTrackDirectoriesByDefault,
+
+        ['#album.directorySuffixForTracks']:
+          albumDirectorySuffixForTracks,
       }) {
-        if (suffixTrackDirectoriesByDefault === true) {
+        if (trackSectionSuffixTrackDirectoriesByDefault === true) {
+          return continuation.raiseOutput({
+            ['#directorySuffix']: trackSectionDirectorySuffixForTracks,
+            ['#directorySuffixWithinAlbum']: trackSectionDirectorySuffixForTracks,
+          });
+        }
+
+        if (trackSectionSuffixTrackDirectoriesByDefault === false) {
+          // Just proceed. Other logic may independently provide a suffix,
+          // but this false ensures that track ignores whether the *album*
+          // provides Suffix Track Directories: true.
+          return continuation();
+        }
+
+        if (albumSuffixTrackDirectoriesByDefault === true) {
           return continuation.raiseOutput({
-            ['#directorySuffix']: directorySuffixForTracks,
+            ['#directorySuffix']: albumDirectorySuffixForTracks,
             ['#directorySuffixWithinAlbum']: null,
           });
         }
@@ -141,29 +190,47 @@ export default templateCompositeFrom({
     },
 
     {
+      // The logic path in this section is ONLY decided based on the track's
+      // actually-set Name Detail, and inheritence is not a factor at all.
       dependencies: [
         '_nameDetail',
-         'nameDetailAcrossWiki',
-
+        '#album.nameDetailForTracks',
+        '#album.directorySuffixForTracks',
+        '#trackSection.nameDetailForTracks',
         '#trackSection.directorySuffixForTracks',
       ],
 
       compute(continuation, {
         ['_nameDetail']: nameDetail,
-        [ 'nameDetailAcrossWiki']: nameDetailAcrossWiki,
+
+        ['#album.nameDetailForTracks']:
+          albumNameDetailForTracks,
+
+        ['#album.directorySuffixForTracks']:
+          albumDirectorySuffixForTracks,
+
+        ['#trackSection.nameDetailForTracks']:
+          trackSectionNameDetailForTracks,
 
         ['#trackSection.directorySuffixForTracks']:
-          directorySuffixForTracks,
+          trackSectionDirectorySuffixForTracks,
       }) {
+        if (nameDetail === 'section') {
+          return continuation.raiseOutput({
+            ['#directorySuffix']: trackSectionDirectorySuffixForTracks,
+            ['#directorySuffixWithinAlbum']: trackSectionDirectorySuffixForTracks,
+          })
+        }
+
         if (nameDetail === 'album') {
           return continuation.raiseOutput({
-            ['#directorySuffix']: directorySuffixForTracks,
-            ['#directorySuffixWithinAlbum']: directorySuffixForTracks,
+            ['#directorySuffix']: albumDirectorySuffixForTracks,
+            ['#directorySuffixWithinAlbum']: null,
           });
         }
 
-        if (nameDetailAcrossWiki) {
-          const kebab = getKebabCase(nameDetailAcrossWiki);
+        if (nameDetail) {
+          const kebab = getKebabCase(nameDetail);
 
           return continuation.raiseOutput({
             ['#directorySuffix']: kebab,
diff --git a/src/data/things/Track.js b/src/data/things/Track.js
index 1f7375be..f6b3346c 100644
--- a/src/data/things/Track.js
+++ b/src/data/things/Track.js
@@ -169,12 +169,12 @@ export class Track extends Thing {
           input.updateValue({
             validate:
               anyOf(
-                isBoolean,
-                is('album'),
+                is(false),
+                is('album', 'section'),
                 isDirectory,
                 strictArrayOf(
                   anyOf(
-                    is('album'),
+                    is('album', 'section'),
                     isDirectory))),
           }),
       }),
@@ -781,21 +781,37 @@ export class Track extends Thing {
         }) =>
           (nameDetail === 'album'
             ? null
+         : nameDetail === 'section'
+            ? null
             : nameDetail),
       },
     ],
 
     nameDetailAcrossWiki: [
       withPropertyFromObject('album', V('nameDetailForTracks')),
+      withPropertyFromObject('trackSection', V('nameDetailForTracks')),
 
       {
-        dependencies: ['_nameDetail', '#album.nameDetailForTracks'],
+        dependencies: [
+          '_nameDetail',
+          '#album.nameDetailForTracks',
+          '#trackSection.nameDetailForTracks',
+        ],
+
         compute: ({
-          ['_nameDetail']: nameDetail,
-          ['#album.nameDetailForTracks']: nameDetailFromAlbum,
+          ['_nameDetail']:
+            nameDetail,
+
+          ['#album.nameDetailForTracks']:
+            albumNameDetailForTracks,
+
+          ['#trackSection.nameDetailForTracks']:
+            trackSectionNameDetailForTracks,
         }) =>
           (nameDetail === 'album'
-            ? nameDetailFromAlbum
+            ? albumNameDetailForTracks
+         : nameDetail === 'section'
+            ? trackSectionNameDetailForTracks
             : nameDetail),
       },
     ],
@@ -1062,7 +1078,14 @@ export class Track extends Thing {
       'Name Detail': {property: 'nameDetail'},
 
       'Directory': {property: 'directory'},
-      'Suffix Directory': {property: 'suffixDirectory'},
+
+      'Suffix Directory': {
+        property: 'suffixDirectory',
+        transform: value =>
+          (value === true
+            ? 'album'
+            : value),
+      },
 
       'Reference By Directory': {property: 'referenceByDirectory'},
 
diff --git a/src/data/things/album/TrackSection.js b/src/data/things/album/TrackSection.js
index 00963d1b..0e6adb6d 100644
--- a/src/data/things/album/TrackSection.js
+++ b/src/data/things/album/TrackSection.js
@@ -13,6 +13,7 @@ import {
   isDirectory,
   isExcludingURLsReason,
   isNumber,
+  isString,
 } from '#validators';
 
 import {withLengthOfList, withNearbyItemFromList, withPropertyFromObject}
@@ -48,6 +49,22 @@ export class TrackSection extends Thing {
 
     name: name(V('Unnamed Track Section')),
 
+    // Track sections don't have a Name Detail themselves, but they do provide
+    // a value which tracks can reference via 'Name Detail: section'.
+    nameDetailForTracks: {
+      flags: {update: true, expose: true},
+
+      update: {validate: isString},
+
+      expose: {
+        dependencies: ['name'],
+        transform: (value, {name}) =>
+          (value
+            ? value
+            : name),
+      },
+    },
+
     unqualifiedDirectory: directory(),
 
     directorySuffixForTracks: [
@@ -55,18 +72,25 @@ export class TrackSection extends Thing {
         validate: input.value(isDirectory),
       }),
 
-      withPropertyFromObject('album', V('directorySuffixForTracks')),
-      exposeDependency('#album.directorySuffixForTracks'),
+      {
+        dependencies: ['unqualifiedDirectory', 'name', 'nameDetailForTracks'],
+        compute: ({unqualifiedDirectory, name, nameDetailForTracks}) =>
+          (nameDetailForTracks === name
+            ? unqualifiedDirectory
+            : getKebabCase(nameDetailForTracks)),
+      },
     ],
 
-    suffixTrackDirectoriesByDefault: [
-      exposeUpdateValueOrContinue({
-        validate: input.value(isBoolean),
-      }),
-
-      withPropertyFromObject('album', V('suffixTrackDirectoriesByDefault')),
-      exposeDependency('#album.suffixTrackDirectoriesByDefault'),
-    ],
+    // Not quite a flag, because it supports (and defaults to) null.
+    // The value false means to explicitly ignore that the album is
+    // providing Suffix Track Directories: true. The value true means
+    // to use the TRACK SECTION's own directory suffix. The value null
+    // defers to the album's suffixTrackDirectoriesByDefault, which is
+    // simply true or false.
+    suffixTrackDirectoriesByDefault: {
+      flags: {expose: true, update: true},
+      update: {validate: isBoolean},
+    },
 
     color: [
       exposeUpdateValueOrContinue({
@@ -204,6 +228,8 @@ export class TrackSection extends Thing {
   static [Thing.yamlDocumentSpec] = {
     fields: {
       'Section': {property: 'name'},
+      'Name Detail For Tracks': {property: 'nameDetailForTracks'},
+
       'Directory Suffix': {property: 'directorySuffixForTracks'},
       'Suffix Track Directories': {property: 'suffixTrackDirectoriesByDefault'},