« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/page/artist.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/page/artist.js')
-rw-r--r--src/page/artist.js593
1 files changed, 92 insertions, 501 deletions
diff --git a/src/page/artist.js b/src/page/artist.js
index 2e87669..f80bd90 100644
--- a/src/page/artist.js
+++ b/src/page/artist.js
@@ -1,512 +1,103 @@
-// Artist page specification.
-//
-// NB: See artist-alias.js for artist alias redirect pages.
-
-// Imports
-
-import fixWS from 'fix-whitespace';
-
-import * as html from '../util/html.js';
-
-import {
-    UNRELEASED_TRACKS_DIRECTORY
-} from '../util/magic-constants.js';
-
-import {
-    bindOpts,
-    unique
-} from '../util/sugar.js';
+import {empty} from '#sugar';
 
-import {
-    chunkByProperties,
-    getTotalDuration,
-    sortByDate
-} from '../util/wiki-data.js';
-
-// Page exports
+export const description = `per-artist info & artwork gallery pages`;
 
+// NB: See artist-alias.js for artist alias redirect pages.
 export function targets({wikiData}) {
-    return wikiData.artistData;
+  return wikiData.artistData.filter(artist => !artist.isAlias);
 }
 
-export function write(artist, {wikiData}) {
-    const { groupData, wikiInfo } = wikiData;
-
-    const {
-        name,
-        urls = [],
-        note = ''
-    } = artist;
-
-    const artThingsAll = sortByDate(unique([...artist.albums.asCoverArtist, ...artist.albums.asWallpaperArtist, ...artist.albums.asBannerArtist, ...artist.tracks.asCoverArtist]));
-    const artThingsGallery = sortByDate([...artist.albums.asCoverArtist, ...artist.tracks.asCoverArtist]);
-    const commentaryThings = sortByDate([...artist.albums.asCommentator, ...artist.tracks.asCommentator]);
-
-    const hasGallery = artThingsGallery.length > 0;
-
-    const getArtistsAndContrib = (thing, key) => ({
-        artists: thing[key]?.filter(({ who }) => who !== artist),
-        contrib: thing[key]?.find(({ who }) => who === artist),
-        thing,
-        key
-    });
-
-    const artListChunks = chunkByProperties(sortByDate(artThingsAll.flatMap(thing =>
-        (['coverArtists', 'wallpaperArtists', 'bannerArtists']
-            .map(key => getArtistsAndContrib(thing, key))
-            .filter(({ contrib }) => contrib)
-            .map(props => ({
-                album: thing.album || thing,
-                track: thing.album ? thing : null,
-                date: +(thing.coverArtDate || thing.date),
-                ...props
-            })))
-    )), ['date', 'album']);
-
-    const commentaryListChunks = chunkByProperties(commentaryThings.map(thing => ({
-        album: thing.album || thing,
-        track: thing.album ? thing : null
-    })), ['album']);
-
-    const allTracks = sortByDate(unique([...artist.tracks.asArtist, ...artist.tracks.asContributor]));
-    const unreleasedTracks = allTracks.filter(track => track.album.directory === UNRELEASED_TRACKS_DIRECTORY);
-    const releasedTracks = allTracks.filter(track => track.album.directory !== UNRELEASED_TRACKS_DIRECTORY);
-
-    const chunkTracks = tracks => (
-        chunkByProperties(tracks.map(track => ({
-            track,
-            date: +track.date,
-            album: track.album,
-            duration: track.duration,
-            artists: (track.artists.some(({ who }) => who === artist)
-                ? track.artists.filter(({ who }) => who !== artist)
-                : track.contributors.filter(({ who }) => who !== artist)),
-            contrib: {
-                who: artist,
-                what: [
-                    track.artists.find(({ who }) => who === artist)?.what,
-                    track.contributors.find(({ who }) => who === artist)?.what
-                ].filter(Boolean).join(', ')
-            }
-        })), ['date', 'album'])
-        .map(({date, album, chunk}) => ({
-            date, album, chunk,
-            duration: getTotalDuration(chunk),
-        })));
-
-    const unreleasedTrackListChunks = chunkTracks(unreleasedTracks);
-    const releasedTrackListChunks = chunkTracks(releasedTracks);
-
-    const totalReleasedDuration = getTotalDuration(releasedTracks);
-
-    const countGroups = things => {
-        const usedGroups = things.flatMap(thing => thing.groups || thing.album?.groups || []);
-        return groupData
-            .map(group => ({
-                group,
-                contributions: usedGroups.filter(g => g === group).length
-            }))
-            .filter(({ contributions }) => contributions > 0)
-            .sort((a, b) => b.contributions - a.contributions);
-    };
-
-    const musicGroups = countGroups(releasedTracks);
-    const artGroups = countGroups(artThingsAll);
-
-    let flashes, flashListChunks;
-    if (wikiInfo.features.flashesAndGames) {
-        flashes = sortByDate(artist.flashes.asContributor.slice());
-        flashListChunks = (
-            chunkByProperties(flashes.map(flash => ({
-                act: flash.act,
-                flash,
-                date: flash.date,
-                // Manual artists/contrib properties here, 8ecause we don't
-                // want to show the full list of other contri8utors inline.
-                // (It can often 8e very, very large!)
-                artists: [],
-                contrib: flash.contributors.find(({ who }) => who === artist)
-            })), ['act'])
-            .map(({ act, chunk }) => ({
-                act, chunk,
-                dateFirst: chunk[0].date,
-                dateLast: chunk[chunk.length - 1].date
-            })));
-    }
-
-    const generateEntryAccents = ({
-        getArtistString, strings,
-        aka, entry, artists, contrib
-    }) =>
-        (aka
-            ? strings('artistPage.creditList.entry.rerelease', {entry})
-            : (artists.length
-                ? (contrib.what
-                    ? strings('artistPage.creditList.entry.withArtists.withContribution', {
-                        entry,
-                        artists: getArtistString(artists),
-                        contribution: contrib.what
-                    })
-                    : strings('artistPage.creditList.entry.withArtists', {
-                        entry,
-                        artists: getArtistString(artists)
-                    }))
-                : (contrib.what
-                    ? strings('artistPage.creditList.entry.withContribution', {
-                        entry,
-                        contribution: contrib.what
-                    })
-                    : entry)));
-
-    const unbound_generateTrackList = (chunks, {
-        getArtistString, link, strings
-    }) => fixWS`
-        <dl>
-            ${chunks.map(({date, album, chunk, duration}) => fixWS`
-                <dt>${strings('artistPage.creditList.album.withDate.withDuration', {
-                    album: link.album(album),
-                    date: strings.count.date(date),
-                    duration: strings.count.duration(duration, {approximate: true})
-                })}</dt>
-                <dd><ul>
-                    ${(chunk
-                        .map(({track, ...props}) => ({
-                            aka: track.aka,
-                            entry: strings('artistPage.creditList.entry.track.withDuration', {
-                                track: link.track(track),
-                                duration: strings.count.duration(track.duration)
-                            }),
-                            ...props
-                        }))
-                        .map(({aka, ...opts}) => html.tag('li',
-                            {class: aka && 'rerelease'},
-                            generateEntryAccents({getArtistString, strings, aka, ...opts})))
-                        .join('\n'))}
-                </ul></dd>
-            `).join('\n')}
-        </dl>
-    `;
-
-    const unbound_serializeArtistsAndContrib = (key, {
-        serializeContribs,
-        serializeLink
-    }) => thing => {
-        const { artists, contrib } = getArtistsAndContrib(thing, key);
-        const ret = {};
-        ret.link = serializeLink(thing);
-        if (contrib.what) ret.contribution = contrib.what;
-        if (artists.length) ret.otherArtists = serializeContribs(artists);
-        return ret;
-    };
-
-    const unbound_serializeTrackListChunks = (chunks, {serializeLink}) =>
-        chunks.map(({date, album, chunk, duration}) => ({
-            album: serializeLink(album),
-            date,
-            duration,
-            tracks: chunk.map(({ track }) => ({
-                link: serializeLink(track),
-                duration: track.duration
-            }))
-        }));
-
-    const data = {
-        type: 'data',
-        path: ['artist', artist.directory],
-        data: ({
-            serializeContribs,
-            serializeLink
-        }) => {
-            const serializeArtistsAndContrib = bindOpts(unbound_serializeArtistsAndContrib, {
-                serializeContribs,
-                serializeLink
-            });
-
-            const serializeTrackListChunks = bindOpts(unbound_serializeTrackListChunks, {
-                serializeLink
-            });
-
-            return {
-                albums: {
-                    asCoverArtist: artist.albums.asCoverArtist.map(serializeArtistsAndContrib('coverArtists')),
-                    asWallpaperArtist: artist.albums.asWallpaperArtist.map(serializeArtistsAndContrib('wallpaperArtists')),
-                    asBannerArtist: artist.albums.asBannerArtist.map(serializeArtistsAndContrib('bannerArtists'))
-                },
-                flashes: wikiInfo.features.flashesAndGames ? {
-                    asContributor: artist.flashes.asContributor
-                        .map(flash => getArtistsAndContrib(flash, 'contributors'))
-                        .map(({ contrib, thing: flash }) => ({
-                            link: serializeLink(flash),
-                            contribution: contrib.what
-                        }))
-                } : null,
-                tracks: {
-                    asArtist: artist.tracks.asArtist.map(serializeArtistsAndContrib('artists')),
-                    asContributor: artist.tracks.asContributor.map(serializeArtistsAndContrib('contributors')),
-                    chunked: {
-                        released: serializeTrackListChunks(releasedTrackListChunks),
-                        unreleased: serializeTrackListChunks(unreleasedTrackListChunks)
-                    }
-                }
-            };
-        }
-    };
-
-    const infoPage = {
-        type: 'page',
-        path: ['artist', artist.directory],
-        page: ({
-            fancifyURL,
-            generateCoverLink,
-            generateInfoGalleryLinks,
-            getArtistString,
-            link,
-            strings,
-            to,
-            transformMultiline
-        }) => {
-            const generateTrackList = bindOpts(unbound_generateTrackList, {
-                getArtistString,
-                link,
-                strings
-            });
-
-            return {
-                title: strings('artistPage.title', {artist: name}),
-
-                main: {
-                    content: fixWS`
-                        ${artist.hasAvatar && generateCoverLink({
-                            path: ['localized.artistAvatar', artist.directory],
-                            alt: strings('misc.alt.artistAvatar')
-                        })}
-                        <h1>${strings('artistPage.title', {artist: name})}</h1>
-                        ${note && fixWS`
-                            <p>${strings('releaseInfo.note')}</p>
-                            <blockquote>
-                                ${transformMultiline(note)}
-                            </blockquote>
-                            <hr>
-                        `}
-                        ${urls.length && `<p>${strings('releaseInfo.visitOn', {
-                            links: strings.list.or(urls.map(url => fancifyURL(url, {strings})))
-                        })}</p>`}
-                        ${hasGallery && `<p>${strings('artistPage.viewArtGallery', {
-                            link: link.artistGallery(artist, {
-                                text: strings('artistPage.viewArtGallery.link')
-                            })
-                        })}</p>`}
-                        <p>${strings('misc.jumpTo.withLinks', {
-                            links: strings.list.unit([
-                                [
-                                    [...releasedTracks, ...unreleasedTracks].length && `<a href="#tracks">${strings('artistPage.trackList.title')}</a>`,
-                                    unreleasedTracks.length && `(<a href="#unreleased-tracks">${strings('artistPage.unreleasedTrackList.title')}</a>)`
-                                ].filter(Boolean).join(' '),
-                                artThingsAll.length && `<a href="#art">${strings('artistPage.artList.title')}</a>`,
-                                wikiInfo.features.flashesAndGames && flashes.length && `<a href="#flashes">${strings('artistPage.flashList.title')}</a>`,
-                                commentaryThings.length && `<a href="#commentary">${strings('artistPage.commentaryList.title')}</a>`
-                            ].filter(Boolean))
-                        })}</p>
-                        ${(releasedTracks.length || unreleasedTracks.length) && fixWS`
-                            <h2 id="tracks">${strings('artistPage.trackList.title')}</h2>
-                        `}
-                        ${releasedTracks.length && fixWS`
-                            <p>${strings('artistPage.contributedDurationLine', {
-                                artist: artist.name,
-                                duration: strings.count.duration(totalReleasedDuration, {approximate: true, unit: true})
-                            })}</p>
-                            <p>${strings('artistPage.musicGroupsLine', {
-                                groups: strings.list.unit(musicGroups
-                                    .map(({ group, contributions }) => strings('artistPage.groupsLine.item', {
-                                        group: link.groupInfo(group),
-                                        contributions: strings.count.contributions(contributions)
-                                    })))
-                            })}</p>
-                            ${generateTrackList(releasedTrackListChunks)}
-                        `}
-                        ${unreleasedTracks.length && fixWS`
-                            <h3 id="unreleased-tracks">${strings('artistPage.unreleasedTrackList.title')}</h3>
-                            ${generateTrackList(unreleasedTrackListChunks)}
-                        `}
-                        ${artThingsAll.length && fixWS`
-                            <h2 id="art">${strings('artistPage.artList.title')}</h2>
-                            ${hasGallery && `<p>${strings('artistPage.viewArtGallery.orBrowseList', {
-                                link: link.artistGallery(artist, {
-                                    text: strings('artistPage.viewArtGallery.link')
-                                })
-                            })}</p>`}
-                            <p>${strings('artistPage.artGroupsLine', {
-                                groups: strings.list.unit(artGroups
-                                    .map(({ group, contributions }) => strings('artistPage.groupsLine.item', {
-                                        group: link.groupInfo(group),
-                                        contributions: strings.count.contributions(contributions)
-                                    })))
-                            })}</p>
-                            <dl>
-                                ${artListChunks.map(({date, album, chunk}) => fixWS`
-                                    <dt>${strings('artistPage.creditList.album.withDate', {
-                                        album: link.album(album),
-                                        date: strings.count.date(date)
-                                    })}</dt>
-                                    <dd><ul>
-                                        ${(chunk
-                                            .map(({album, track, key, ...props}) => ({
-                                                entry: (track
-                                                    ? strings('artistPage.creditList.entry.track', {
-                                                        track: link.track(track)
-                                                    })
-                                                    : `<i>${strings('artistPage.creditList.entry.album.' + {
-                                                        wallpaperArtists: 'wallpaperArt',
-                                                        bannerArtists: 'bannerArt',
-                                                        coverArtists: 'coverArt'
-                                                    }[key])}</i>`),
-                                                ...props
-                                            }))
-                                            .map(opts => generateEntryAccents({getArtistString, strings, ...opts}))
-                                            .map(row => `<li>${row}</li>`)
-                                            .join('\n'))}
-                                    </ul></dd>
-                                `).join('\n')}
-                            </dl>
-                        `}
-                        ${wikiInfo.features.flashesAndGames && flashes.length && fixWS`
-                            <h2 id="flashes">${strings('artistPage.flashList.title')}</h2>
-                            <dl>
-                                ${flashListChunks.map(({act, chunk, dateFirst, dateLast}) => fixWS`
-                                    <dt>${strings('artistPage.creditList.flashAct.withDateRange', {
-                                        act: link.flash(chunk[0].flash, {text: act.name}),
-                                        dateRange: strings.count.dateRange([dateFirst, dateLast])
-                                    })}</dt>
-                                    <dd><ul>
-                                        ${(chunk
-                                            .map(({flash, ...props}) => ({
-                                                entry: strings('artistPage.creditList.entry.flash', {
-                                                    flash: link.flash(flash)
-                                                }),
-                                                ...props
-                                            }))
-                                            .map(opts => generateEntryAccents({getArtistString, strings, ...opts}))
-                                            .map(row => `<li>${row}</li>`)
-                                            .join('\n'))}
-                                    </ul></dd>
-                                `).join('\n')}
-                            </dl>
-                        `}
-                        ${commentaryThings.length && fixWS`
-                            <h2 id="commentary">${strings('artistPage.commentaryList.title')}</h2>
-                            <dl>
-                                ${commentaryListChunks.map(({album, chunk}) => fixWS`
-                                    <dt>${strings('artistPage.creditList.album', {
-                                        album: link.album(album)
-                                    })}</dt>
-                                    <dd><ul>
-                                        ${(chunk
-                                            .map(({album, track, ...props}) => track
-                                                ? strings('artistPage.creditList.entry.track', {
-                                                    track: link.track(track)
-                                                })
-                                                : `<i>${strings('artistPage.creditList.entry.album.commentary')}</i>`)
-                                            .map(row => `<li>${row}</li>`)
-                                            .join('\n'))}
-                                    </ul></dd>
-                                `).join('\n')}
-                            </dl>
-                        `}
-                    `
-                },
-
-                nav: generateNavForArtist(artist, false, hasGallery, {
-                    generateInfoGalleryLinks,
-                    link,
-                    strings,
-                    wikiData
-                })
-            };
-        }
-    };
-
-    const galleryPage = hasGallery && {
-        type: 'page',
-        path: ['artistGallery', artist.directory],
-        page: ({
-            generateInfoGalleryLinks,
-            getAlbumCover,
-            getGridHTML,
-            getTrackCover,
-            link,
-            strings,
-            to
-        }) => ({
-            title: strings('artistGalleryPage.title', {artist: name}),
-
-            main: {
-                classes: ['top-index'],
-                content: fixWS`
-                    <h1>${strings('artistGalleryPage.title', {artist: name})}</h1>
-                    <p class="quick-info">${strings('artistGalleryPage.infoLine', {
-                        coverArts: strings.count.coverArts(artThingsGallery.length, {unit: true})
-                    })}</p>
-                    <div class="grid-listing">
-                        ${getGridHTML({
-                            entries: artThingsGallery.map(item => ({item})),
-                            srcFn: thing => (thing.album
-                                ? getTrackCover(thing)
-                                : getAlbumCover(thing)),
-                            hrefFn: thing => (thing.album
-                                ? to('localized.track', thing.directory)
-                                : to('localized.album', thing.directory))
-                        })}
-                    </div>
-                `
-            },
-
-            nav: generateNavForArtist(artist, true, hasGallery, {
-                generateInfoGalleryLinks,
-                link,
-                strings,
-                wikiData
-            })
-        })
-    };
-
-    return [data, infoPage, galleryPage].filter(Boolean);
+export function pathsForTarget(artist) {
+  const hasGalleryPage =
+    !empty(artist.tracksAsCoverArtist) ||
+    !empty(artist.albumsAsCoverArtist);
+
+  return [
+    {
+      type: 'page',
+      path: ['artist', artist.directory],
+
+      contentFunction: {
+        name: 'generateArtistInfoPage',
+        args: [artist],
+      },
+    },
+
+    hasGalleryPage && {
+      type: 'page',
+      path: ['artistGallery', artist.directory],
+
+      contentFunction: {
+        name: 'generateArtistGalleryPage',
+        args: [artist],
+      },
+    },
+  ];
 }
 
-// Utility functions
-
-function generateNavForArtist(artist, isGallery, hasGallery, {
-    generateInfoGalleryLinks,
-    link,
-    strings,
-    wikiData
-}) {
-    const { wikiInfo } = wikiData;
+/*
+const unbound_serializeArtistsAndContrib =
+  (key, {serializeContribs, serializeLink}) =>
+  (thing) => {
+    const {artists, contrib} = getArtistsAndContrib(thing, key);
+    const ret = {};
+    ret.link = serializeLink(thing);
+    if (contrib.what) ret.contribution = contrib.what;
+    if (!empty(artists)) ret.otherArtists = serializeContribs(artists);
+    return ret;
+  };
+
+const unbound_serializeTrackListChunks = (chunks, {serializeLink}) =>
+  chunks.map(({date, album, chunk, duration}) => ({
+    album: serializeLink(album),
+    date,
+    duration,
+    tracks: chunk.map(({track}) => ({
+      link: serializeLink(track),
+      duration: track.duration,
+    })),
+  }));
+
+const data = {
+  type: 'data',
+  path: ['artist', artist.directory],
+  data: ({serializeContribs, serializeLink}) => {
+    const serializeArtistsAndContrib = bindOpts(unbound_serializeArtistsAndContrib, {
+      serializeContribs,
+      serializeLink,
+    });
 
-    const infoGalleryLinks = (hasGallery &&
-        generateInfoGalleryLinks(artist, isGallery, {
-            link, strings,
-            linkKeyGallery: 'artistGallery',
-            linkKeyInfo: 'artist'
-        }))
+    const serializeTrackListChunks = bindOpts(unbound_serializeTrackListChunks, {
+      serializeLink,
+    });
 
     return {
-        links: [
-            {toHome: true},
-            wikiInfo.features.listings &&
-            {
-                path: ['localized.listingIndex'],
-                title: strings('listingIndex.title')
-            },
-            {
-                html: strings('artistPage.nav.artist', {
-                    artist: link.artist(artist, {class: 'current'})
-                })
-            },
-            hasGallery &&
-            {
-                divider: false,
-                html: `(${infoGalleryLinks})`
-            }
-        ]
+      albums: {
+        asCoverArtist: artist.albumsAsCoverArtist
+          .map(serializeArtistsAndContrib('coverArtistContribs')),
+        asWallpaperArtist: artist.albumsAsWallpaperArtist
+          .map(serializeArtistsAndContrib('wallpaperArtistContribs')),
+        asBannerArtist: artist.albumsAsBannerArtis
+          .map(serializeArtistsAndContrib('bannerArtistContribs')),
+      },
+      flashes: wikiInfo.enableFlashesAndGames
+        ? {
+            asContributor: artist.flashesAsContributor
+              .map(flash => getArtistsAndContrib(flash, 'contributorContribs'))
+              .map(({contrib, thing: flash}) => ({
+                link: serializeLink(flash),
+                contribution: contrib.what,
+              })),
+          }
+        : null,
+      tracks: {
+        asArtist: artist.tracksAsArtist
+          .map(serializeArtistsAndContrib('artistContribs')),
+        asContributor: artist.tracksAsContributo
+          .map(serializeArtistsAndContrib('contributorContribs')),
+        chunked: serializeTrackListChunks(trackListChunks),
+      },
     };
-}
+  },
+};
+*/