« 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/album.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/page/album.js')
-rw-r--r--src/page/album.js667
1 files changed, 248 insertions, 419 deletions
diff --git a/src/page/album.js b/src/page/album.js
index b68189f..af41076 100644
--- a/src/page/album.js
+++ b/src/page/album.js
@@ -1,443 +1,272 @@
-// Album page specification.
-
-// Imports
-
-import fixWS from 'fix-whitespace';
-
-import * as html from '../util/html.js';
-
-import {
-    bindOpts,
-    compareArrays,
-} from '../util/sugar.js';
-
-import {
-    getAlbumCover,
-    getAlbumListTag,
-    getTotalDuration,
-} from '../util/wiki-data.js';
-
-// Page exports
+export const description = `per-album info, artwork gallery & commentary pages`;
 
 export function targets({wikiData}) {
-    return wikiData.albumData;
+  return wikiData.albumData;
 }
 
-export function write(album, {wikiData}) {
-    const { wikiInfo } = wikiData;
+export function pathsForTarget(album) {
+  const hasCommentaryPage = !!album.commentary || album.tracks.some(t => t.commentary);
 
-    const unbound_trackToListItem = (track, {
-        getArtistString,
-        getLinkThemeString,
-        link,
-        language
-    }) => {
-        const itemOpts = {
-            duration: language.formatDuration(track.duration ?? 0),
-            track: link.track(track)
-        };
-        return `<li style="${getLinkThemeString(track.color)}">${
-            (compareArrays(
-                track.artistContribs.map(c => c.who),
-                album.artistContribs.map(c => c.who),
-                {checkOrder: false})
-                ? language.$('trackList.item.withDuration', itemOpts)
-                : language.$('trackList.item.withDuration.withArtists', {
-                    ...itemOpts,
-                    by: `<span class="by">${
-                        language.$('trackList.item.withArtists.by', {
-                            artists: getArtistString(track.artistContribs)
-                        })
-                    }</span>`
-                }))
-        }</li>`;
-    };
+  return [
+    {
+      type: 'page',
+      path: ['album', album.directory],
 
-    const hasCommentaryEntries = ([album, ...album.tracks].filter(x => x.commentary).length > 0);
-    const hasAdditionalFiles = (album.additionalFiles?.length > 0);
-    const albumDuration = getTotalDuration(album.tracks);
+      contentFunction: {
+        name: 'generateAlbumInfoPage',
+        args: [album],
+      },
+    },
 
-    const listTag = getAlbumListTag(album);
-
-    const data = {
-        type: 'data',
-        path: ['album', album.directory],
-        data: ({
-            serializeContribs,
-            serializeCover,
-            serializeGroupsForAlbum,
-            serializeLink
-        }) => ({
-            name: album.name,
-            directory: album.directory,
-            dates: {
-                released: album.date,
-                trackArtAdded: album.trackArtDate,
-                coverArtAdded: album.coverArtDate,
-                addedToWiki: album.dateAddedToWiki
-            },
-            duration: albumDuration,
-            color: album.color,
-            cover: serializeCover(album, getAlbumCover),
-            artistContribs: serializeContribs(album.artistContribs),
-            coverArtistContribs: serializeContribs(album.coverArtistContribs),
-            wallpaperArtistContribs: serializeContribs(album.wallpaperArtistContribs),
-            bannerArtistContribs: serializeContribs(album.bannerArtistContribs),
-            groups: serializeGroupsForAlbum(album),
-            trackGroups: album.trackGroups?.map(trackGroup => ({
-                name: trackGroup.name,
-                color: trackGroup.color,
-                tracks: trackGroup.tracks.map(track => track.directory)
-            })),
-            tracks: album.tracks.map(track => ({
-                link: serializeLink(track),
-                duration: track.duration
-            }))
-        })
-    };
-
-    const page = {
-        type: 'page',
-        path: ['album', album.directory],
-        page: ({
-            fancifyURL,
-            generateAdditionalFilesShortcut,
-            generateAdditionalFilesList,
-            generateChronologyLinks,
-            generateCoverLink,
-            getAlbumCover,
-            getAlbumStylesheet,
-            getArtistString,
-            getLinkThemeString,
-            getSizeOfAdditionalFile,
-            getThemeString,
-            link,
-            language,
-            transformMultiline,
-            urls,
-        }) => {
-            const trackToListItem = bindOpts(unbound_trackToListItem, {
-                getArtistString,
-                getLinkThemeString,
-                link,
-                language
-            });
-
-            const cover = getAlbumCover(album);
-
-            return {
-                title: language.$('albumPage.title', {album: album.name}),
-                stylesheet: getAlbumStylesheet(album),
-                theme: getThemeString(album.color, [
-                    `--album-directory: ${album.directory}`
-                ]),
-
-                banner: album.bannerArtistContribs.length && {
-                    dimensions: album.bannerDimensions,
-                    path: ['media.albumBanner', album.directory, album.bannerFileExtension],
-                    alt: language.$('misc.alt.albumBanner'),
-                    position: 'top'
-                },
-
-                main: {
-                    content: fixWS`
-                        ${cover && generateCoverLink({
-                            src: cover,
-                            alt: language.$('misc.alt.albumCover'),
-                            tags: album.artTags
-                        })}
-                        <h1>${language.$('albumPage.title', {album: album.name})}</h1>
-                        <p>
-                            ${[
-                                album.artistContribs.length && language.$('releaseInfo.by', {
-                                    artists: getArtistString(album.artistContribs, {
-                                        showContrib: true,
-                                        showIcons: true
-                                    })
-                                }),
-                                album.coverArtistContribs.length && language.$('releaseInfo.coverArtBy', {
-                                    artists: getArtistString(album.coverArtistContribs, {
-                                        showContrib: true,
-                                        showIcons: true
-                                    })
-                                }),
-                                album.wallpaperArtistContribs.length && language.$('releaseInfo.wallpaperArtBy', {
-                                    artists: getArtistString(album.wallpaperArtistContribs, {
-                                        showContrib: true,
-                                        showIcons: true
-                                    })
-                                }),
-                                album.bannerArtistContribs.length && language.$('releaseInfo.bannerArtBy', {
-                                    artists: getArtistString(album.bannerArtistContribs, {
-                                        showContrib: true,
-                                        showIcons: true
-                                    })
-                                }),
-                                album.date && language.$('releaseInfo.released', {
-                                    date: language.formatDate(album.date)
-                                }),
-                                (album.coverArtDate &&
-                                    +album.coverArtDate !== +album.date &&
-                                    language.$('releaseInfo.artReleased', {
-                                        date: language.formatDate(album.coverArtDate)
-                                    })),
-                                language.$('releaseInfo.duration', {
-                                    duration: language.formatDuration(albumDuration, {approximate: album.tracks.length > 1})
-                                })
-                            ].filter(Boolean).join('<br>\n')}
-                        </p>
-                        ${(hasAdditionalFiles || hasCommentaryEntries) && fixWS`<p>
-                            ${[
-                                hasAdditionalFiles && generateAdditionalFilesShortcut(album.additionalFiles, {language}),
-                                hasCommentaryEntries && language.$('releaseInfo.viewCommentary', {
-                                    link: link.albumCommentary(album, {
-                                        text: language.$('releaseInfo.viewCommentary.link')
-                                    })
-                                })
-                            ].filter(Boolean).join('<br>\n')
-                        }</p>`}
-                        ${album.urls?.length && `<p>${
-                            language.$('releaseInfo.listenOn', {
-                                links: language.formatDisjunctionList(album.urls.map(url => fancifyURL(url, {album: true})))
-                            })
-                        }</p>`}
-                        ${album.trackGroups && (album.trackGroups.length > 1 || !album.trackGroups[0].isDefaultTrackGroup) ? fixWS`
-                            <dl class="album-group-list">
-                                ${album.trackGroups.map(({ name, color, startIndex, tracks }) => fixWS`
-                                    <dt>${
-                                        language.$('trackList.section.withDuration', {
-                                            duration: language.formatDuration(getTotalDuration(tracks), {approximate: tracks.length > 1}),
-                                            section: name
-                                        })
-                                    }</dt>
-                                    <dd><${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}>
-                                        ${tracks.map(trackToListItem).join('\n')}
-                                    </${listTag}></dd>
-                                `).join('\n')}
-                            </dl>
-                        ` : fixWS`
-                            <${listTag}>
-                                ${album.tracks.map(trackToListItem).join('\n')}
-                            </${listTag}>
-                        `}
-                        ${album.dateAddedToWiki && fixWS`
-                            <p>
-                                ${[
-                                    language.$('releaseInfo.addedToWiki', {
-                                        date: language.formatDate(album.dateAddedToWiki)
-                                    })
-                                ].filter(Boolean).join('<br>\n')}
-                            </p>
-                        `}
-                        ${hasAdditionalFiles && generateAdditionalFilesList(album.additionalFiles, {
-                            // TODO: Kinda near the metal here...
-                            getFileSize: file => getSizeOfAdditionalFile(urls
-                                .from('media.root')
-                                .to('media.albumAdditionalFile', album.directory, file)),
-                            linkFile: file => link.albumAdditionalFile({album, file}),
-                        })}
-                        ${album.commentary && fixWS`
-                            <p>${language.$('releaseInfo.artistCommentary')}</p>
-                            <blockquote>
-                                ${transformMultiline(album.commentary)}
-                            </blockquote>
-                        `}
-                    `
-                },
-
-                sidebarLeft: generateAlbumSidebar(album, null, {
-                    fancifyURL,
-                    getLinkThemeString,
-                    link,
-                    language,
-                    transformMultiline,
-                    wikiData
-                }),
-
-                nav: {
-                    links: [
-                        {toHome: true},
-                        {
-                            html: language.$('albumPage.nav.album', {
-                                album: link.album(album, {class: 'current'})
-                            })
-                        },
-                        album.tracks.length > 1 &&
-                        {
-                            divider: false,
-                            html: generateAlbumNavLinks(album, null, {language})
-                        }
-                    ],
-                    content: html.tag('div', generateAlbumChronologyLinks(album, null, {generateChronologyLinks}))
-                }
-            };
-        }
-    };
+    {
+      type: 'page',
+      path: ['albumGallery', album.directory],
 
-    return [page, data];
-}
+      contentFunction: {
+        name: 'generateAlbumGalleryPage',
+        args: [album],
+      },
+    },
 
-// Utility functions
+    hasCommentaryPage && {
+      type: 'page',
+      path: ['albumCommentary', album.directory],
 
-export function generateAlbumSidebar(album, currentTrack, {
-    fancifyURL,
-    getLinkThemeString,
-    link,
-    language,
-    transformMultiline,
-    wikiData
-}) {
-    const listTag = getAlbumListTag(album);
+      contentFunction: {
+        name: 'generateAlbumCommentaryPage',
+        args: [album],
+      },
+    },
 
     /*
-    const trackGroups = album.trackGroups || [{
-        name: language.$('albumSidebar.trackList.fallbackGroupName'),
-        color: album.color,
-        startIndex: 0,
-        tracks: album.tracks
-    }];
+    {
+      type: 'data',
+      path: ['album', album.directory],
+
+      contentFunction: {
+        name: 'generateAlbumDataFile',
+        args: [album],
+      },
+    },
     */
+  ];
+}
 
-    const { trackGroups } = album;
-
-    const trackToListItem = track => html.tag('li',
-        {class: track === currentTrack && 'current'},
-        language.$('albumSidebar.trackList.item', {
-            track: link.track(track)
-        }));
-
-    const nameOrDefault = (isDefaultTrackGroup, name) =>
-        (isDefaultTrackGroup
-            ? language.$('albumSidebar.trackList.fallbackGroupName')
-            : name);
+export function pathsTargetless({wikiData: {wikiInfo}}) {
+  return [
+    {
+      type: 'page',
+      path: ['commentaryIndex'],
+      contentFunction: {name: 'generateCommentaryIndexPage'},
+    },
+
+    wikiInfo.canonicalBase === 'https://hsmusic.wiki/' &&
+      {
+        type: 'redirect',
+        fromPath: ['page', 'list/all-commentary'],
+        toPath: ['commentaryIndex'],
+        title: 'Album Commentary',
+      },
+  ];
+}
 
-    const trackListPart = fixWS`
-        <h1>${link.album(album)}</h1>
-        ${trackGroups.map(({ name, color, startIndex, tracks, isDefaultTrackGroup }) =>
-            html.tag('details', {
-                // Leave side8ar track groups collapsed on al8um homepage,
-                // since there's already a view of all the groups expanded
-                // in the main content area.
-                open: currentTrack && tracks.includes(currentTrack),
-                class: tracks.includes(currentTrack) && 'current'
-            }, [
-                html.tag('summary',
-                    {style: getLinkThemeString(color)},
-                    (listTag === 'ol'
-                        ? language.$('albumSidebar.trackList.group.withRange', {
-                            group: `<span class="group-name">${nameOrDefault(isDefaultTrackGroup, name)}</span>`,
-                            range: `${startIndex + 1}&ndash;${startIndex + tracks.length}`
-                        })
-                        : language.$('albumSidebar.trackList.group', {
-                            group: `<span class="group-name">${nameOrDefault(isDefaultTrackGroup, name)}</span>`
-                        }))
-                ),
-                fixWS`
-                    <${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}>
-                        ${tracks.map(trackToListItem).join('\n')}
-                    </${listTag}>
-                `
-            ])).join('\n')}
-    `;
+/*
+export function write(album, {wikiData}) {
+  const getSocialEmbedDescription = ({
+    getArtistString: _getArtistString,
+    language,
+  }) => {
+    const hasDuration = albumDuration > 0;
+    const hasTracks = album.tracks.length > 0;
+    const hasDate = !!album.date;
+    if (!hasDuration && !hasTracks && !hasDate) return '';
+
+    return language.formatString(
+      'albumPage.socialEmbed.body' + [
+        hasDuration && '.withDuration',
+        hasTracks && '.withTracks',
+        hasDate && '.withReleaseDate',
+      ].filter(Boolean).join(''),
+      Object.fromEntries([
+        hasDuration &&
+          ['duration', language.formatDuration(albumDuration)],
+        hasTracks &&
+          ['tracks', language.countTracks(album.tracks.length, {unit: true})],
+        hasDate &&
+          ['date', language.formatDate(album.date)],
+      ].filter(Boolean)));
+  };
+
+  const data = {
+    type: 'data',
+    path: ['album', album.directory],
+    data: ({
+      serializeContribs,
+      serializeCover,
+      serializeGroupsForAlbum,
+      serializeLink,
+    }) => ({
+      name: album.name,
+      directory: album.directory,
+      dates: {
+        released: album.date,
+        trackArtAdded: album.trackArtDate,
+        coverArtAdded: album.coverArtDate,
+        addedToWiki: album.dateAddedToWiki,
+      },
+      duration: albumDuration,
+      color: album.color,
+      cover: serializeCover(album, getAlbumCover),
+      artistContribs: serializeContribs(album.artistContribs),
+      coverArtistContribs: serializeContribs(album.coverArtistContribs),
+      wallpaperArtistContribs: serializeContribs(album.wallpaperArtistContribs),
+      bannerArtistContribs: serializeContribs(album.bannerArtistContribs),
+      groups: serializeGroupsForAlbum(album),
+      trackSections: album.trackSections?.map((section) => ({
+        name: section.name,
+        color: section.color,
+        tracks: section.tracks.map((track) => track.directory),
+      })),
+      tracks: album.tracks.map((track) => ({
+        link: serializeLink(track),
+        duration: track.duration,
+      })),
+    }),
+  };
+
+  // TODO: only gen if there are any tracks with art
+  const galleryPage = {
+    type: 'page',
+    path: ['albumGallery', album.directory],
+    page: ({
+      // generateInfoGalleryLinks,
+      // generateNavigationLinks,
+      getAlbumCover,
+      getAlbumStylesheet,
+      getGridHTML,
+      getTrackCover,
+      // getLinkThemeString,
+      getThemeString,
+      html,
+      language,
+      link,
+    }) => ({
+      title: language.$('albumGalleryPage.title', {album: album.name}),
+      stylesheet: getAlbumStylesheet(album),
+
+      themeColor: album.color,
+      theme: getThemeString(album.color),
+
+      main: {
+        classes: ['top-index'],
+        headingMode: 'static',
+
+        content: [
+          html.tag('p',
+            {class: 'quick-info'},
+            (album.date
+              ? language.$('albumGalleryPage.infoLine.withDate', {
+                  tracks: html.tag('b',
+                    language.countTracks(album.tracks.length, {unit: true})),
+                  duration: html.tag('b',
+                    language.formatDuration(albumDuration, {unit: true})),
+                  date: html.tag('b',
+                    language.formatDate(album.date)),
+                })
+              : language.$('albumGalleryPage.infoLine', {
+                  tracks: html.tag('b',
+                    language.countTracks(album.tracks.length, {unit: true})),
+                  duration: html.tag('b',
+                    language.formatDuration(albumDuration, {unit: true})),
+                }))),
+
+          html.tag('div',
+            {class: 'grid-listing'},
+            getGridHTML({
+              linkFn: (t, opts) => t.album ? link.track(t, opts) : link.album(t, opts),
+              noSrcTextFn: t =>
+                language.$('misc.albumGalleryGrid.noCoverArt', {
+                  name: t.name,
+                }),
 
-    const { groups } = album;
+              srcFn(t) {
+                if (!t.album) {
+                  return getAlbumCover(t);
+                } else if (t.hasUniqueCoverArt) {
+                  return getTrackCover(t);
+                } else {
+                  return null;
+                }
+              },
 
-    const groupParts = groups.map(group => {
-        const albums = group.albums.filter(album => album.date);
-        const index = albums.indexOf(album);
-        const next = index >= 0 && albums[index + 1];
-        const previous = index > 0 && albums[index - 1];
-        return {group, next, previous};
-    }).map(({group, next, previous}) => fixWS`
-        <h1>${
-            language.$('albumSidebar.groupBox.title', {
-                group: link.groupInfo(group)
-            })
-        }</h1>
-        ${!currentTrack && transformMultiline(group.descriptionShort)}
-        ${group.urls?.length && `<p>${
-            language.$('releaseInfo.visitOn', {
-                links: language.formatDisjunctionList(group.urls.map(url => fancifyURL(url)))
-            })
-        }</p>`}
-        ${!currentTrack && fixWS`
-            ${next && `<p class="group-chronology-link">${
-                language.$('albumSidebar.groupBox.next', {
-                    album: link.album(next)
-                })
-            }</p>`}
-            ${previous && `<p class="group-chronology-link">${
-                language.$('albumSidebar.groupBox.previous', {
-                    album: link.album(previous)
-                })
-            }</p>`}
-        `}
-    `);
+              entries: [
+                // {item: album},
+                ...album.tracks.map(track => ({item: track})),
+              ],
+            })),
+        ],
+      },
 
-    if (groupParts.length) {
-        if (currentTrack) {
-            const combinedGroupPart = groupParts.join('\n<hr>\n');
-            return {
-                multiple: [
-                    trackListPart,
-                    combinedGroupPart
-                ]
-            };
-        } else {
-            return {
-                multiple: [
-                    ...groupParts,
-                    trackListPart
-                ]
-            };
-        }
-    } else {
-        return {
-            content: trackListPart
-        };
-    }
+      nav: generateAlbumExtrasPageNav(album, 'gallery', {
+        html,
+        language,
+        link,
+      }),
+    }),
+  };
 }
 
-export function generateAlbumNavLinks(album, currentTrack, {
-    generatePreviousNextLinks,
-    language
+export function generateAlbumSecondaryNav(album, currentTrack, {
+  getLinkThemeString,
+  html,
+  language,
+  link,
 }) {
-    if (album.tracks.length <= 1) {
-        return '';
-    }
-
-    const previousNextLinks = currentTrack && generatePreviousNextLinks(currentTrack, {
-        data: album.tracks,
-        linkKey: 'track'
+  const isAlbumPage = !currentTrack;
+
+  const {groups} = album;
+
+  if (empty(groups)) {
+    return null;
+  }
+
+  const groupParts = groups
+    .map((group) => {
+      const albums = group.albums.filter((album) => album.date);
+      const index = albums.indexOf(album);
+      const next = index >= 0 && albums[index + 1];
+      const previous = index > 0 && albums[index - 1];
+      return {group, next, previous};
+    })
+    .map(({group, next, previous}) => {
+      const previousLink =
+        isAlbumPage &&
+        previous &&
+          link.album(previous, {
+            color: false,
+            text: language.$('misc.nav.previous'),
+          });
+      const nextLink =
+        isAlbumPage &&
+        next &&
+          link.album(next, {
+            color: false,
+            text: language.$('misc.nav.next'),
+          });
+      const links = [previousLink, nextLink].filter(Boolean);
+      return html.tag('span',
+        {style: getLinkThemeString(group.color)},
+        [
+          language.$('albumSidebar.groupBox.title', {
+            group: link.groupInfo(group),
+          }),
+          !empty(links) && `(${language.formatUnitList(links)})`,
+        ]);
     });
-    const randomLink = `<a href="#" data-random="track-in-album" id="random-button">${
-        (currentTrack
-            ? language.$('trackPage.nav.random')
-            : language.$('albumPage.nav.randomTrack'))
-    }</a>`;
-
-    return (previousNextLinks
-        ? `(${previousNextLinks}<span class="js-hide-until-data">, ${randomLink}</span>)`
-        : `<span class="js-hide-until-data">(${randomLink})</span>`);
-}
 
-export function generateAlbumChronologyLinks(album, currentTrack, {generateChronologyLinks}) {
-    return [
-        currentTrack && generateChronologyLinks(currentTrack, {
-            contribKey: 'artistContribs',
-            getThings: artist => [...artist.tracksAsArtist, ...artist.tracksAsContributor],
-            headingString: 'misc.chronology.heading.track'
-        }),
-        currentTrack && generateChronologyLinks(currentTrack, {
-            contribKey: 'contributorContribs',
-            getThings: artist => [...artist.tracksAsArtist, ...artist.tracksAsContributor],
-            headingString: 'misc.chronology.heading.track'
-        }),
-        generateChronologyLinks(currentTrack || album, {
-            contribKey: 'coverArtistContribs',
-            dateKey: 'coverArtDate',
-            getThings: artist => [...artist.albumsAsCoverArtist, ...artist.tracksAsCoverArtist],
-            headingString: 'misc.chronology.heading.coverArt'
-        })
-    ].filter(Boolean).join('\n');
+  return {
+    classes: ['nav-links-groups'],
+    content: groupParts,
+  };
 }
+*/