« get me outta code hell

find.js « util « src - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/util/find.js
blob: 0e22063493d3f93859620a5a8926e2a66ef125ee (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import {
    logError,
    logWarn
} from './cli.js';

function findHelper(keys, dataProp, findFns = {}) {
    const byDirectory = findFns.byDirectory || matchDirectory;
    const byName = findFns.byName || matchName;

    const keyRefRegex = new RegExp(String.raw`^(?:(${keys.join('|')}):(?=\S))?(.*)$`);

    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[2];

        const data = wikiData[dataProp];

        const found = (key
            ? byDirectory(ref, data)
            : byName(ref, data));

        if (!found) {
            logWarn`Didn't match anything for ${fullRef}!`;
        }

        return found;
    };
}

function matchDirectory(ref, data) {
    return data.find(({ directory }) => directory === ref);
}

function matchName(ref, data) {
    const matches = data.filter(({ name }) => name.toLowerCase() === ref.toLowerCase());

    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;
    }

    if (matches.length === 0) {
        return null;
    }

    const thing = matches[0];

    if (ref !== thing.name) {
        logWarn`Bad capitalization: ${'\x1b[31m' + ref} -> ${'\x1b[32m' + thing.name}`;
    }

    return thing;
}

function matchTagName(ref, data) {
    return matchName(ref.startsWith('cw: ') ? ref.slice(4) : ref, data);
}

const find = {
    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'], 'artTagData', {byName: matchTagName}),
    track: findHelper(['track'], 'trackData')
};

export default find;