« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/data/things/content.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/data/things/content.js')
-rw-r--r--src/data/things/content.js223
1 files changed, 176 insertions, 47 deletions
diff --git a/src/data/things/content.js b/src/data/things/content.js
index cf8fa1f4..64d03e69 100644
--- a/src/data/things/content.js
+++ b/src/data/things/content.js
@@ -1,10 +1,13 @@
-import {input} from '#composite';
-import find from '#find';
+import {input, V} from '#composite';
+import {transposeArrays} from '#sugar';
 import Thing from '#thing';
-import {is, isDate} from '#validators';
+import {is, isDate, validateReferenceList} from '#validators';
 import {parseDate} from '#yaml';
 
-import {contentString, referenceList, simpleDate, soupyFind, thing}
+import {withFilteredList, withMappedList, withPropertyFromList}
+  from '#composite/data';
+import {withResolvedReferenceList} from '#composite/wiki-data';
+import {contentString, simpleDate, soupyFind, thing}
   from '#composite/wiki-properties';
 
 import {
@@ -17,22 +20,34 @@ import {
 } from '#composite/control-flow';
 
 import {
-  contentArtists,
   hasAnnotationPart,
-  withAnnotationParts,
-  withHasAnnotationPart,
-  withSourceText,
-  withSourceURLs,
+  withAnnotationPartNodeLists,
+  withExpressedOrImplicitArtistReferences,
   withWebArchiveDate,
 } from '#composite/things/content';
 
 export class ContentEntry extends Thing {
-  static [Thing.getPropertyDescriptors] = ({Artist}) => ({
+  static [Thing.getPropertyDescriptors] = () => ({
     // Update & expose
 
     thing: thing(),
 
-    artists: contentArtists(),
+    artists: [
+      withExpressedOrImplicitArtistReferences({
+        from: input.updateValue({
+          validate: validateReferenceList('artist'),
+        }),
+      }),
+
+      exitWithoutDependency('#artistReferences', V([])),
+
+      withResolvedReferenceList({
+        list: '#artistReferences',
+        find: soupyFind.input('artist'),
+      }),
+
+      exposeDependency('#resolvedReferenceList'),
+    ],
 
     artistText: contentString(),
 
@@ -51,6 +66,8 @@ export class ContentEntry extends Thing {
     },
 
     accessKind: [
+      exitWithoutDependency('_accessDate'),
+
       exposeUpdateValueOrContinue({
         validate: input.value(
           is(...[
@@ -61,9 +78,7 @@ export class ContentEntry extends Thing {
 
       withWebArchiveDate(),
 
-      withResultOfAvailabilityCheck({
-        from: '#webArchiveDate',
-      }),
+      withResultOfAvailabilityCheck({from: '#webArchiveDate'}),
 
       {
         dependencies: ['#availability'],
@@ -73,13 +88,10 @@ export class ContentEntry extends Thing {
             : continuation()),
       },
 
-      exposeConstant({
-        value: input.value(null),
-      }),
+      exposeConstant(V('accessed')),
     ],
 
     date: simpleDate(),
-
     secondDate: simpleDate(),
 
     accessDate: [
@@ -93,9 +105,7 @@ export class ContentEntry extends Thing {
         dependency: '#webArchiveDate',
       }),
 
-      exposeConstant({
-        value: input.value(null),
-      }),
+      exposeConstant(V(null)),
     ],
 
     body: contentString(),
@@ -106,22 +116,114 @@ export class ContentEntry extends Thing {
 
     // Expose only
 
+    isContentEntry: exposeConstant(V(true)),
+
     annotationParts: [
-      withAnnotationParts({
-        mode: input.value('strings'),
-      }),
+      withAnnotationPartNodeLists(),
+
+      {
+        dependencies: ['#annotationPartNodeLists'],
+        compute: (continuation, {
+          ['#annotationPartNodeLists']: nodeLists,
+        }) => continuation({
+          ['#firstNodes']:
+            nodeLists.map(list => list.at(0)),
+
+          ['#lastNodes']:
+            nodeLists.map(list => list.at(-1)),
+        }),
+      },
 
-      exposeDependency({dependency: '#annotationParts'}),
+      withPropertyFromList('#firstNodes', V('i'))
+        .outputs({'#firstNodes.i': '#startIndices'}),
+
+      withPropertyFromList('#lastNodes', V('iEnd'))
+        .outputs({'#lastNodes.iEnd': '#endIndices'}),
+
+      {
+        dependencies: [
+          'annotation',
+          '#startIndices',
+          '#endIndices',
+        ],
+
+        compute: ({
+          ['annotation']: annotation,
+          ['#startIndices']: startIndices,
+          ['#endIndices']: endIndices,
+        }) =>
+          transposeArrays([startIndices, endIndices])
+            .map(([start, end]) =>
+              annotation.slice(start, end)),
+      },
     ],
 
     sourceText: [
-      withSourceText(),
-      exposeDependency({dependency: '#sourceText'}),
+      withAnnotationPartNodeLists(),
+
+      {
+        dependencies: ['#annotationPartNodeLists'],
+        compute: (continuation, {
+          ['#annotationPartNodeLists']: nodeLists,
+        }) => continuation({
+          ['#firstPartWithExternalLink']:
+            nodeLists
+              .find(nodes => nodes
+                .some(node => node.type === 'external-link')) ??
+            null,
+        }),
+      },
+
+      exitWithoutDependency('#firstPartWithExternalLink'),
+
+      {
+        dependencies: ['annotation', '#firstPartWithExternalLink'],
+        compute: ({
+          ['annotation']: annotation,
+          ['#firstPartWithExternalLink']: nodes,
+        }) =>
+          annotation.slice(
+            nodes.at(0).i,
+            nodes.at(-1).iEnd),
+      },
     ],
 
     sourceURLs: [
-      withSourceURLs(),
-      exposeDependency({dependency: '#sourceURLs'}),
+      withAnnotationPartNodeLists(),
+
+      {
+        dependencies: ['#annotationPartNodeLists'],
+        compute: (continuation, {
+          ['#annotationPartNodeLists']: nodeLists,
+        }) => continuation({
+          ['#firstPartWithExternalLink']:
+            nodeLists
+              .find(nodes => nodes
+                .some(node => node.type === 'external-link')) ??
+            null,
+        }),
+      },
+
+      exitWithoutDependency('#firstPartWithExternalLink', V([])),
+
+      withMappedList({
+        list: '#firstPartWithExternalLink',
+        map: input.value(node => node.type === 'external-link'),
+      }).outputs({
+        '#mappedList': '#externalLinkFilter',
+      }),
+
+      withFilteredList({
+        list: '#firstPartWithExternalLink',
+        filter: '#externalLinkFilter',
+      }),
+
+      withMappedList({
+        list: '#filteredList',
+        map: input.value(node => node.data.href),
+      }),
+
+      exposeDependency('#mappedList'),
     ],
   });
 
@@ -145,9 +247,17 @@ export class ContentEntry extends Thing {
 }
 
 export class CommentaryEntry extends ContentEntry {
+  static [Thing.wikiData] = 'commentaryData';
+
   static [Thing.getPropertyDescriptors] = () => ({
     // Expose only
 
+    isCommentaryEntry: [
+      exposeConstant({
+        value: input.value(true),
+      }),
+    ],
+
     isWikiEditorCommentary: hasAnnotationPart({
       part: input.value('wiki editor'),
     }),
@@ -155,28 +265,23 @@ export class CommentaryEntry extends ContentEntry {
 }
 
 export class LyricsEntry extends ContentEntry {
+  static [Thing.wikiData] = 'lyricsData';
+
   static [Thing.getPropertyDescriptors] = () => ({
-    // Expose only
+    // Update & expose
 
-    isWikiLyrics: hasAnnotationPart({
-      part: input.value('wiki lyrics'),
-    }),
+    originDetails: contentString(),
 
-    hasSquareBracketAnnotations: [
-      withHasAnnotationPart({
-        part: input.value('wiki lyrics'),
-      }),
+    // Expose only
 
-      exitWithoutDependency({
-        dependency: '#hasAnnotationPart',
-        mode: input.value('falsy'),
-        value: input.value(false),
-      }),
+    isLyricsEntry: exposeConstant(V(true)),
 
-      exitWithoutDependency({
-        dependency: 'body',
-        value: input.value(false),
-      }),
+    isWikiLyrics: hasAnnotationPart(V('wiki lyrics')),
+    helpNeeded: hasAnnotationPart(V('help needed')),
+
+    hasSquareBracketAnnotations: [
+      exitWithoutDependency('isWikiLyrics', V(false), V('falsy')),
+      exitWithoutDependency('body', V(false)),
 
       {
         dependencies: ['body'],
@@ -185,6 +290,30 @@ export class LyricsEntry extends ContentEntry {
       },
     ],
   });
+
+  static [Thing.yamlDocumentSpec] = Thing.extendDocumentSpec(ContentEntry, {
+    fields: {
+      'Origin Details': {property: 'originDetails'},
+    },
+  });
+}
+
+export class CreditingSourcesEntry extends ContentEntry {
+  static [Thing.wikiData] = 'creditingSourceData';
+
+  static [Thing.getPropertyDescriptors] = () => ({
+    // Expose only
+
+    isCreditingSourcesEntry: exposeConstant(V(true)),
+  });
 }
 
-export class CreditingSourcesEntry extends ContentEntry {}
+export class ReferencingSourcesEntry extends ContentEntry {
+  static [Thing.wikiData] = 'referencingSourceData';
+
+  static [Thing.getPropertyDescriptors] = () => ({
+    // Expose only
+
+    isReferencingSourceEntry: exposeConstant(V(true)),
+  });
+}