« get me outta code hell

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:
Diffstat (limited to 'src/util')
-rw-r--r--src/util/find.js75
-rw-r--r--src/util/replacer.js12
2 files changed, 50 insertions, 37 deletions
diff --git a/src/util/find.js b/src/util/find.js
index e8e04a5b..fc82ba9e 100644
--- a/src/util/find.js
+++ b/src/util/find.js
@@ -1,9 +1,21 @@
 import {
+    color,
     logError,
     logWarn
 } from './cli.js';
 
-function findHelper(keys, dataProp, findFns = {}) {
+function warnOrThrow(mode, message) {
+    switch (mode) {
+        case 'error':
+            throw new Error(message);
+        case 'warn':
+            logWarn(message);
+        default:
+            return null;
+    }
+}
+
+function findHelper(keys, findFns = {}) {
     // Note: This cache explicitly *doesn't* support mutable data arrays. If the
     // data array is modified, make sure it's actually a new array object, not
     // the original, or the cache here will break and act as though the data
@@ -15,18 +27,24 @@ function findHelper(keys, dataProp, findFns = {}) {
 
     const keyRefRegex = new RegExp(String.raw`^(?:(${keys.join('|')}):(?=\S))?(.*)$`);
 
-    return (fullRef, {wikiData, quiet = false}) => {
+    // The mode argument here may be 'warn', 'error', or 'quiet'. 'error' throws
+    // errors for null matches (with details about the error), while 'warn' and
+    // 'quiet' both return null, with 'warn' logging details directly to the
+    // console.
+    return (fullRef, data, {mode = 'warn'} = {}) => {
         if (!fullRef) return null;
         if (typeof fullRef !== 'string') {
             throw new Error(`Got a reference that is ${typeof fullRef}, not string: ${fullRef}`);
         }
 
-        const data = wikiData[dataProp];
-
         if (!data) {
             throw new Error(`Expected data to be present`);
         }
 
+        if (!Array.isArray(data) && data.wikiData) {
+            throw new Error(`Old {wikiData: {...}} format provided`);
+        }
+
         let cacheForThisData = cache.get(data);
         const cachedValue = cacheForThisData?.[fullRef];
         if (cachedValue) {
@@ -40,18 +58,18 @@ function findHelper(keys, dataProp, findFns = {}) {
 
         const match = fullRef.match(keyRefRegex);
         if (!match) {
-            throw new Error(`Malformed link reference: "${fullRef}"`);
+            return warnOrThrow(mode, `Malformed link reference: "${fullRef}"`);
         }
 
         const key = match[1];
         const ref = match[2];
 
         const found = (key
-            ? byDirectory(ref, data, quiet)
-            : byName(ref, data, quiet));
+            ? byDirectory(ref, data, mode)
+            : byName(ref, data, mode));
 
-        if (!found && !quiet) {
-            logWarn`Didn't match anything for ${fullRef}!`;
+        if (!found) {
+            warnOrThrow(mode, `Didn't match anything for ${color.bright(fullRef)}`);
         }
 
         cacheForThisData[fullRef] = found;
@@ -60,23 +78,18 @@ function findHelper(keys, dataProp, findFns = {}) {
     };
 }
 
-function matchDirectory(ref, data, quiet) {
+function matchDirectory(ref, data, mode) {
     return data.find(({ directory }) => directory === ref);
 }
 
-function matchName(ref, data, quiet) {
+function matchName(ref, data, mode) {
     const matches = data.filter(({ name }) => name.toLowerCase() === ref.toLowerCase());
 
     if (matches.length > 1) {
-        // TODO: This should definitely be a thrown error.
-        if (!quiet) {
-            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;
+        return warnOrThrow(mode,
+            `Multiple matches for reference "${ref}". Please resolve:\n` +
+            matches.map(match => `- ${match.name} (${match.directory})\n`).join('') +
+            `Returning null for this reference.`);
     }
 
     if (matches.length === 0) {
@@ -85,8 +98,8 @@ function matchName(ref, data, quiet) {
 
     const thing = matches[0];
 
-    if (ref !== thing.name && !quiet) {
-        logWarn`Bad capitalization: ${'\x1b[31m' + ref} -> ${'\x1b[32m' + thing.name}`;
+    if (ref !== thing.name) {
+        warnOrThrow(mode, `Bad capitalization: ${color.red(ref)} -> ${color.green(thing.name)}`);
     }
 
     return thing;
@@ -97,15 +110,15 @@ function matchTagName(ref, data, quiet) {
 }
 
 const find = {
-    album: findHelper(['album', 'album-commentary'], 'albumData'),
-    artist: findHelper(['artist', 'artist-gallery'], 'artistData'),
-    artTag: findHelper(['tag'], 'artTagData', {byName: matchTagName}),
-    flash: findHelper(['flash'], 'flashData'),
-    group: findHelper(['group', 'group-gallery'], 'groupData'),
-    listing: findHelper(['listing'], 'listingSpec'),
-    newsEntry: findHelper(['news-entry'], 'newsData'),
-    staticPage: findHelper(['static'], 'staticPageData'),
-    track: findHelper(['track'], 'trackData')
+    album: findHelper(['album', 'album-commentary']),
+    artist: findHelper(['artist', 'artist-gallery']),
+    artTag: findHelper(['tag'], {byName: matchTagName}),
+    flash: findHelper(['flash']),
+    group: findHelper(['group', 'group-gallery']),
+    listing: findHelper(['listing']),
+    newsEntry: findHelper(['news-entry']),
+    staticPage: findHelper(['static']),
+    track: findHelper(['track'])
 };
 
 export default find;
diff --git a/src/util/replacer.js b/src/util/replacer.js
index 6c524778..0066d218 100644
--- a/src/util/replacer.js
+++ b/src/util/replacer.js
@@ -1,8 +1,7 @@
-import find from './find.js';
 import {logError, logWarn} from './cli.js';
 import {escapeRegex} from './sugar.js';
 
-export function validateReplacerSpec(replacerSpec, link) {
+export function validateReplacerSpec(replacerSpec, {find, link}) {
     let success = true;
 
     for (const [key, {link: linkKey, find: findKey, value, html}] of Object.entries(replacerSpec)) {
@@ -320,7 +319,7 @@ export function parseInput(input) {
 }
 
 function evaluateTag(node, opts) {
-    const { input, link, replacerSpec, strings, to, wikiData } = opts;
+    const { find, input, link, replacerSpec, strings, to, wikiData } = opts;
 
     const source = input.slice(node.i, node.iEnd);
 
@@ -348,7 +347,7 @@ function evaluateTag(node, opts) {
         valueFn ? valueFn(replacerValue) :
         findKey ? find[findKey]((replacerKeyImplied
             ? replacerValue
-            : replacerKey + `:` + replacerValue), {wikiData}) :
+            : replacerKey + `:` + replacerValue)) :
         {
             directory: replacerValue,
             name: null
@@ -417,13 +416,14 @@ function transformNodes(nodes, opts) {
     return nodes.map(node => transformNode(node, opts)).join('');
 }
 
-export function transformInline(input, {replacerSpec, link, strings, to, wikiData}) {
+export function transformInline(input, {replacerSpec, find, link, strings, to, wikiData}) {
     if (!replacerSpec) throw new Error('Expected replacerSpec');
+    if (!find) throw new Error('Expected find');
     if (!link) throw new Error('Expected link');
     if (!strings) throw new Error('Expected strings');
     if (!to) throw new Error('Expected to');
     if (!wikiData) throw new Error('Expected wikiData');
 
     const nodes = parseInput(input);
-    return transformNodes(nodes, {input, link, replacerSpec, strings, to, wikiData});
+    return transformNodes(nodes, {input, find, link, replacerSpec, strings, to, wikiData});
 }