« get me outta code hell

data: add additionalNames wiki property ("Additional Names") - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/data
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-11-20 19:32:03 -0400
committer(quasar) nebula <qznebula@protonmail.com>2023-11-21 07:50:14 -0400
commitbde469f4cede426bd9baa8981b876e82ae290972 (patch)
tree5bd945a7159dca0d050a84f3ea6913e83e9471e2 /src/data
parent765e039ef94f7cd1365ba9f211bd686beab5e8ec (diff)
data: add additionalNames wiki property ("Additional Names")
Diffstat (limited to 'src/data')
-rw-r--r--src/data/composite/wiki-properties/additionalNameList.js13
-rw-r--r--src/data/composite/wiki-properties/index.js1
-rw-r--r--src/data/things/track.js2
-rw-r--r--src/data/things/validators.js7
-rw-r--r--src/data/yaml.js20
5 files changed, 43 insertions, 0 deletions
diff --git a/src/data/composite/wiki-properties/additionalNameList.js b/src/data/composite/wiki-properties/additionalNameList.js
new file mode 100644
index 00000000..d1302224
--- /dev/null
+++ b/src/data/composite/wiki-properties/additionalNameList.js
@@ -0,0 +1,13 @@
+// A list of additional names! These can be used for a variety of purposes,
+// e.g. providing extra searchable titles, localizations, romanizations or
+// original titles, and so on. Each item has a name and, optionally, a
+// descriptive annotation.
+
+import {isAdditionalNameList} from '#validators';
+
+export default function() {
+  return {
+    flags: {update: true, expose: true},
+    update: {validate: isAdditionalNameList},
+  };
+}
diff --git a/src/data/composite/wiki-properties/index.js b/src/data/composite/wiki-properties/index.js
index 2462b047..7607e361 100644
--- a/src/data/composite/wiki-properties/index.js
+++ b/src/data/composite/wiki-properties/index.js
@@ -1,4 +1,5 @@
 export {default as additionalFiles} from './additionalFiles.js';
+export {default as additionalNameList} from './additionalNameList.js';
 export {default as color} from './color.js';
 export {default as commentary} from './commentary.js';
 export {default as commentatorArtists} from './commentatorArtists.js';
diff --git a/src/data/things/track.js b/src/data/things/track.js
index 8d310611..f6320677 100644
--- a/src/data/things/track.js
+++ b/src/data/things/track.js
@@ -24,6 +24,7 @@ import {
 
 import {
   additionalFiles,
+  additionalNameList,
   commentary,
   commentatorArtists,
   contributionList,
@@ -63,6 +64,7 @@ export class Track extends Thing {
 
     name: name('Unnamed Track'),
     directory: directory(),
+    additionalNames: additionalNameList(),
 
     duration: duration(),
     urls: urls(),
diff --git a/src/data/things/validators.js b/src/data/things/validators.js
index 19ad1c0a..71570c5a 100644
--- a/src/data/things/validators.js
+++ b/src/data/things/validators.js
@@ -373,6 +373,13 @@ export function isURL(string) {
   return true;
 }
 
+export const isAdditionalName = validateProperties({
+  name: isName,
+  annotation: optional(isStringNonEmpty),
+});
+
+export const isAdditionalNameList = validateArrayItems(isAdditionalName);
+
 export function validateReference(type = 'track') {
   return (ref) => {
     isStringNonEmpty(ref);
diff --git a/src/data/yaml.js b/src/data/yaml.js
index 67cd8db7..cde4413b 100644
--- a/src/data/yaml.js
+++ b/src/data/yaml.js
@@ -436,6 +436,7 @@ export const processTrackSectionDocument = makeProcessDocument(T.TrackSectionHel
 
 export const processTrackDocument = makeProcessDocument(T.Track, {
   fieldTransformations: {
+    'Additional Names': parseAdditionalNames,
     'Duration': parseDuration,
 
     'Date First Released': (value) => new Date(value),
@@ -457,6 +458,7 @@ export const processTrackDocument = makeProcessDocument(T.Track, {
   propertyFieldMapping: {
     name: 'Track',
     directory: 'Directory',
+    additionalNames: 'Additional Names',
     duration: 'Duration',
     color: 'Color',
     urls: 'URLs',
@@ -741,6 +743,24 @@ export function parseContributors(contributionStrings) {
   });
 }
 
+export function parseAdditionalNames(additionalNameStrings) {
+  if (!Array.isArray(additionalNameStrings)) {
+    return additionalNameStrings;
+  }
+
+  return additionalNameStrings.map(additionalNameString => {
+    if (typeof additionalNameString !== 'string') return additionalNameString;
+
+    const match = additionalNameString.match(extractAccentRegex);
+    if (!match) return additionalNameString;
+
+    return {
+      name: match.groups.main,
+      annotation: match.groups.accent ?? null,
+    };
+  });
+}
+
 function parseDimensions(string) {
   // It's technically possible to pass an array like [30, 40] through here.
   // That's not really an issue because if it isn't of the appropriate shape,