« get me outta code hell

refine link/ref resolving & data post-processing - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/util
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2022-01-03 23:23:12 -0400
committer(quasar) nebula <qznebula@protonmail.com>2022-01-03 23:23:12 -0400
commit416b7261fa3c9e3d0873fdc9faf501014462e06c (patch)
tree2a67c7b0bdc2d4fd98d700207e33ac166165280e /src/util
parent22e1c9e1f57a9d2252b6bc614ca8abb805721d4d (diff)
refine link/ref resolving & data post-processing
Diffstat (limited to 'src/util')
-rw-r--r--src/util/find.js83
-rw-r--r--src/util/replacer.js9
2 files changed, 64 insertions, 28 deletions
diff --git a/src/util/find.js b/src/util/find.js
index 1cbeb82..5f69bbe 100644
--- a/src/util/find.js
+++ b/src/util/find.js
@@ -1,15 +1,36 @@
 import {
+    logError,
     logWarn
 } from './cli.js';
 
-function findHelper(keys, dataProp, findFn) {
-    return (ref, {wikiData}) => {
-        if (!ref) return null;
-        ref = ref.replace(new RegExp(`^(${keys.join('|')}):`), '');
+function findHelper(keys, dataProp, findFns = {}) {
+    const byDirectory = findFns.byDirectory || matchDirectory;
+    const byName = findFns.byName || matchName;
+
+    const keyRefRegex = new RegExp(`^((${keys.join('|')}):)?(.*)$`);
+
+    return (fullRef, {wikiData}) => {
+        if (!fullRef) return null;
+        if (typeof fullRef !== 'string') {
+            throw new Error(`Got a reference that is ${typeof fullRef}, not string: ${fullRef}`);
+        }
+
+        const match = fullRef.match(keyRefRegex);
+        if (!match) {
+            throw new Error(`Malformed link reference: "${fullRef}"`);
+        }
+
+        const key = match[1];
+        const ref = match[3];
+
+        const data = wikiData[dataProp];
+
+        const found = (key
+            ? byDirectory(ref, data)
+            : byName(ref, data));
 
-        const found = findFn(ref, wikiData[dataProp]);
         if (!found) {
-            logWarn`Didn't match anything for ${ref}! (${keys.join(', ')})`;
+            logWarn`Didn't match anything for ${fullRef}!`;
         }
 
         return found;
@@ -20,35 +41,45 @@ function matchDirectory(ref, data) {
     return data.find(({ directory }) => directory === ref);
 }
 
-function matchDirectoryOrName(ref, data) {
-    let thing;
+function matchName(ref, data) {
+    const matches = data.filter(({ name }) => name.toLowerCase() === ref.toLowerCase());
 
-    thing = matchDirectory(ref, data);
-    if (thing) return thing;
+    if (matches.length > 1) {
+        logError`Multiple matches for reference "${ref}". Please resolve:`;
+        for (const match of matches) {
+            logError`- ${match.name} (${match.directory})`;
+        }
+        logError`Returning null for this reference.`;
+        return null;
+    }
 
-    thing = data.find(({ name }) => name === ref);
-    if (thing) return thing;
+    if (matches.length === 0) {
+        return null;
+    }
 
-    thing = data.find(({ name }) => name.toLowerCase() === ref.toLowerCase());
-    if (thing) {
+    const thing = matches[0];
+
+    if (ref !== thing.name) {
         logWarn`Bad capitalization: ${'\x1b[31m' + ref} -> ${'\x1b[32m' + thing.name}`;
-        return thing;
     }
 
-    return null;
+    return thing;
+}
+
+function matchTagName(ref, data) {
+    return matchName(ref.startsWith('cw: ') ? ref.slice(4) : ref, data);
 }
 
 const find = {
-    album: findHelper(['album', 'album-commentary'], 'albumData', matchDirectoryOrName),
-    artist: findHelper(['artist', 'artist-gallery'], 'artistData', matchDirectoryOrName),
-    flash: findHelper(['flash'], 'flashData', matchDirectory),
-    group: findHelper(['group', 'group-gallery'], 'groupData', matchDirectoryOrName),
-    listing: findHelper(['listing'], 'listingSpec', matchDirectory),
-    newsEntry: findHelper(['news-entry'], 'newsData', matchDirectory),
-    staticPage: findHelper(['static'], 'staticPageData', matchDirectory),
-    tag: findHelper(['tag'], 'tagData', (ref, data) =>
-        matchDirectoryOrName(ref.startsWith('cw: ') ? ref.slice(4) : ref, data)),
-    track: findHelper(['track'], 'trackData', matchDirectoryOrName)
+    album: findHelper(['album', 'album-commentary'], 'albumData'),
+    artist: findHelper(['artist', 'artist-gallery'], 'artistData'),
+    flash: findHelper(['flash'], 'flashData'),
+    group: findHelper(['group', 'group-gallery'], 'groupData'),
+    listing: findHelper(['listing'], 'listingSpec'),
+    newsEntry: findHelper(['news-entry'], 'newsData'),
+    staticPage: findHelper(['static'], 'staticPageData'),
+    tag: findHelper(['tag'], 'tagData', {byName: matchTagName}),
+    track: findHelper(['track'], 'trackData')
 };
 
 export default find;
diff --git a/src/util/replacer.js b/src/util/replacer.js
index 0c16dc8..6c52477 100644
--- a/src/util/replacer.js
+++ b/src/util/replacer.js
@@ -324,7 +324,10 @@ function evaluateTag(node, opts) {
 
     const source = input.slice(node.i, node.iEnd);
 
-    const replacerKey = node.data.replacerKey?.data || 'track';
+    const replacerKeyImplied = !node.data.replacerKey;
+    const replacerKey = (replacerKeyImplied
+        ? 'track'
+        : node.data.replacerKey.data);
 
     if (!replacerSpec[replacerKey]) {
         logWarn`The link ${source} has an invalid replacer key!`;
@@ -343,7 +346,9 @@ function evaluateTag(node, opts) {
 
     const value = (
         valueFn ? valueFn(replacerValue) :
-        findKey ? find[findKey](replacerValue, {wikiData}) :
+        findKey ? find[findKey]((replacerKeyImplied
+            ? replacerValue
+            : replacerKey + `:` + replacerValue), {wikiData}) :
         {
             directory: replacerValue,
             name: null