diff options
Diffstat (limited to 'src/page')
-rw-r--r-- | src/page/album.js | 704 | ||||
-rw-r--r-- | src/page/artist.js | 680 | ||||
-rw-r--r-- | src/page/index.js | 54 | ||||
-rw-r--r-- | src/page/static.js | 30 | ||||
-rw-r--r-- | src/page/track.js | 550 |
5 files changed, 86 insertions, 1932 deletions
diff --git a/src/page/album.js b/src/page/album.js index 9ee57c09..111cab82 100644 --- a/src/page/album.js +++ b/src/page/album.js @@ -1,66 +1,62 @@ // Album page specification. -import { - bindOpts, - compareArrays, - empty, -} from '../util/sugar.js'; - -import { - getAlbumCover, - getAlbumListTag, - getTotalDuration, -} from '../util/wiki-data.js'; - export const description = `per-album info & track artwork gallery pages`; export function targets({wikiData}) { return wikiData.albumData; } -export function write(album, {wikiData}) { - const unbound_trackToListItem = (track, { - getArtistString, - getLinkThemeString, - html, - language, - link, - }) => { - const itemOpts = { - duration: language.formatDuration(track.duration ?? 0), - track: link.track(track), - }; +export function pathsForTarget(album) { + const hasGalleryPage = album.tracks.some(t => t.hasUniqueCoverArt); + const hasCommentaryPage = !!album.commentary || album.tracks.some(t => t.commentary); - return html.tag('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: html.tag('span', - {class: 'by'}, - language.$('trackList.item.withArtists.by', { - artists: getArtistString(track.artistContribs), - })), - })); - }; + return [ + { + type: 'page', + path: ['album', album.directory], - const hasAdditionalFiles = !empty(album.additionalFiles); - const numAdditionalFiles = album.additionalFiles.flatMap((g) => g.files).length; + contentFunction: { + name: 'generateAlbumInfoPage', + args: [album], + }, + }, - const albumDuration = getTotalDuration(album.tracks); + /* + hasGalleryPage && { + type: 'page', + path: ['albumGallery', album.directory], - const displayTrackSections = - album.trackSections && - (album.trackSections.length > 1 || - !album.trackSections[0]?.isDefaultTrackSection); + contentFunction: { + name: 'generateAlbumGalleryPage', + args: [album], + }, + }, + + hasCommentaryPage && { + type: 'page', + path: ['albumCommentary', album.directory], + + contentFunction: { + name: 'generateAlbumCommentaryPage', + args: [album], + }, + }, - const listTag = getAlbumListTag(album); + { + type: 'data', + path: ['album', album.directory], + contentFunction: { + name: 'generateAlbumDataFile', + args: [album], + }, + }, + */ + ]; +} + +/* +export function write(album, {wikiData}) { const getSocialEmbedDescription = ({ getArtistString: _getArtistString, language, @@ -123,297 +119,6 @@ export function write(album, {wikiData}) { }), }; - const infoPage = { - type: 'page', - path: ['album', album.directory], - page: ({ - absoluteTo, - fancifyURL, - generateAdditionalFilesShortcut, - generateAdditionalFilesList, - generateChronologyLinks, - generateContentHeading, - generateNavigationLinks, - getAlbumCover, - getAlbumStylesheet, - getArtistString, - getLinkThemeString, - getSizeOfAdditionalFile, - getThemeString, - html, - link, - language, - transformMultiline, - urls, - }) => { - const trackToListItem = bindOpts(unbound_trackToListItem, { - getArtistString, - getLinkThemeString, - html, - language, - link, - }); - - return { - title: language.$('albumPage.title', {album: album.name}), - stylesheet: getAlbumStylesheet(album), - - themeColor: album.color, - theme: - getThemeString(album.color, { - additionalVariables: [ - `--album-directory: ${album.directory}`, - ], - }), - - socialEmbed: { - heading: - (empty(album.groups) - ? '' - : language.$('albumPage.socialEmbed.heading', { - group: album.groups[0].name, - })), - headingLink: - (empty(album.groups) - ? null - : absoluteTo('localized.album', album.groups[0].directory)), - title: language.$('albumPage.socialEmbed.title', { - album: album.name, - }), - description: getSocialEmbedDescription({getArtistString, language}), - image: '/' + getAlbumCover(album, {to: urls.from('shared.root').to}), - color: album.color, - }, - - banner: !empty(album.bannerArtistContribs) && { - dimensions: album.bannerDimensions, - path: [ - 'media.albumBanner', - album.directory, - album.bannerFileExtension, - ], - alt: language.$('misc.alt.albumBanner'), - position: 'top', - }, - - cover: { - src: getAlbumCover(album), - alt: language.$('misc.alt.albumCover'), - artTags: album.artTags, - }, - - main: { - headingMode: 'sticky', - - content: [ - html.tag('p', - { - [html.onlyIfContent]: true, - [html.joinChildren]: '<br>', - }, - [ - !empty(album.artistContribs) && - language.$('releaseInfo.by', { - artists: getArtistString(album.artistContribs, { - showContrib: true, - showIcons: true, - }), - }), - - !empty(album.coverArtistContribs) && - language.$('releaseInfo.coverArtBy', { - artists: getArtistString(album.coverArtistContribs, { - showContrib: true, - showIcons: true, - }), - }), - - !empty(album.wallpaperArtistContribs) && - language.$('releaseInfo.wallpaperArtBy', { - artists: getArtistString(album.wallpaperArtistContribs, { - showContrib: true, - showIcons: true, - }), - }), - - !empty(album.bannerArtistContribs) && - language.$('releaseInfo.bannerArtBy', { - artists: getArtistString(album.bannerArtistContribs, { - showContrib: true, - showIcons: true, - }), - }), - - album.date && - language.$('releaseInfo.released', { - date: language.formatDate(album.date), - }), - - album.hasCoverArt && - album.coverArtDate && - +album.coverArtDate !== +album.date && - language.$('releaseInfo.artReleased', { - date: language.formatDate(album.coverArtDate), - }), - - albumDuration > 0 && - language.$('releaseInfo.duration', { - duration: language.formatDuration(albumDuration, { - approximate: album.tracks.length > 1, - }), - }), - ]), - - html.tag('p', - { - [html.onlyIfContent]: true, - [html.joinChildren]: '<br>', - }, - [ - hasAdditionalFiles && - generateAdditionalFilesShortcut(album.additionalFiles), - - checkGalleryPage(album) && - language.$('releaseInfo.viewGallery', { - link: link.albumGallery(album, { - text: language.$('releaseInfo.viewGallery.link'), - }), - }), - - checkCommentaryPage(album) && - language.$('releaseInfo.viewCommentary', { - link: link.albumCommentary(album, { - text: language.$('releaseInfo.viewCommentary.link'), - }), - }), - ]), - - !empty(album.urls) && - html.tag('p', - language.$('releaseInfo.listenOn', { - links: language.formatDisjunctionList( - album.urls.map(url => fancifyURL(url, {album: true})) - ), - })), - - displayTrackSections && - !empty(album.trackSections) && - html.tag('dl', - {class: 'album-group-list'}, - album.trackSections.flatMap(({ - name, - startIndex, - tracks, - }) => [ - html.tag('dt', - {class: ['content-heading']}, - language.$('trackList.section.withDuration', { - duration: language.formatDuration(getTotalDuration(tracks), { - approximate: tracks.length > 1, - }), - section: name, - })), - html.tag('dd', - html.tag(listTag, - listTag === 'ol' ? {start: startIndex + 1} : {}, - tracks.map(trackToListItem))), - ])), - - !displayTrackSections && - !empty(album.tracks) && - html.tag(listTag, - album.tracks.map(trackToListItem)), - - html.tag('p', - { - [html.onlyIfContent]: true, - [html.joinChildren]: '<br>', - }, - [ - album.dateAddedToWiki && - language.$('releaseInfo.addedToWiki', { - date: language.formatDate( - album.dateAddedToWiki - ), - }) - ]), - - ...html.fragment( - hasAdditionalFiles && [ - generateContentHeading({ - id: 'additional-files', - title: language.$('releaseInfo.additionalFiles.heading', { - additionalFiles: language.countAdditionalFiles(numAdditionalFiles, { - unit: true, - }), - }), - }), - - generateAlbumAdditionalFilesList(album, album.additionalFiles, { - generateAdditionalFilesList, - getSizeOfAdditionalFile, - link, - urls, - }), - ]), - - ...html.fragment( - album.commentary && [ - generateContentHeading({ - id: 'artist-commentary', - title: language.$('releaseInfo.artistCommentary'), - }), - - html.tag('blockquote', transformMultiline(album.commentary)), - ]), - ], - }, - - sidebarLeft: generateAlbumSidebar(album, null, { - fancifyURL, - getLinkThemeString, - html, - link, - language, - transformMultiline, - wikiData, - }), - - nav: { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - { - html: language.$('albumPage.nav.album', { - album: link.album(album, {class: 'current'}), - }), - }, - { - divider: false, - html: generateAlbumNavLinks(album, null, { - generateNavigationLinks, - html, - language, - link, - }), - } - ], - content: generateAlbumChronologyLinks(album, null, { - generateChronologyLinks, - html, - }), - }, - - secondaryNav: generateAlbumSecondaryNav(album, null, { - getLinkThemeString, - html, - language, - link, - }), - }; - }, - }; - // TODO: only gen if there are any tracks with art const galleryPage = { type: 'page', @@ -494,153 +199,6 @@ export function write(album, {wikiData}) { }), }), }; - - return [ - infoPage, - galleryPage, - data, - ]; -} - -// Utility functions - -export function generateAlbumSidebar(album, currentTrack, { - fancifyURL, - getLinkThemeString, - html, - language, - link, - transformMultiline, -}) { - const isAlbumPage = !currentTrack; - const isTrackPage = !!currentTrack; - - const listTag = getAlbumListTag(album); - - const {trackSections} = album; - - const trackToListItem = (track) => - html.tag('li', - {class: track === currentTrack && 'current'}, - language.$('albumSidebar.trackList.item', { - track: link.track(track), - })); - - const nameOrDefault = (isDefaultTrackSection, name) => - isDefaultTrackSection - ? language.$('albumSidebar.trackList.fallbackSectionName') - : name; - - const trackListPart = [ - html.tag('h1', link.album(album)), - ...trackSections.map(({name, color, startIndex, tracks, isDefaultTrackSection}) => { - const groupName = - html.tag('span', - {class: 'group-name'}, - nameOrDefault( - isDefaultTrackSection, - name - )); - return 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: isTrackPage && tracks.includes(currentTrack), - class: tracks.includes(currentTrack) && 'current', - }, - [ - html.tag( - 'summary', - {style: getLinkThemeString(color)}, - html.tag('span', [ - listTag === 'ol' && - language.$('albumSidebar.trackList.group.withRange', { - group: groupName, - range: `${startIndex + 1}–${ - startIndex + tracks.length - }`, - }), - listTag === 'ul' && - language.$('albumSidebar.trackList.group', { - group: groupName, - }), - ])), - html.tag(listTag, - listTag === 'ol' ? {start: startIndex + 1} : {}, - tracks.map(trackToListItem)), - ]); - }), - ]; - - const {groups} = album; - - 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}; - }) - // This is a map and not a flatMap because the distinction between which - // group sets of elements belong to matters. That means this variable is an - // array of arrays, and we'll need to treat it as such later! - .map(({group, next, previous}) => [ - html.tag('h1', language.$('albumSidebar.groupBox.title', { - group: link.groupInfo(group), - })), - - isAlbumPage && - transformMultiline(group.descriptionShort), - - !empty(group.urls) && - html.tag('p', language.$('releaseInfo.visitOn', { - links: language.formatDisjunctionList( - group.urls.map((url) => fancifyURL(url)) - ), - })), - - ...html.fragment( - isAlbumPage && [ - next && - html.tag('p', - {class: 'group-chronology-link'}, - language.$('albumSidebar.groupBox.next', { - album: link.album(next), - })), - - previous && - html.tag('p', - {class: 'group-chronology-link'}, - language.$('albumSidebar.groupBox.previous', { - album: link.album(previous), - })), - ]), - ]); - - if (empty(groupParts)) { - return { - stickyMode: 'column', - content: trackListPart, - }; - } else if (isTrackPage) { - const combinedGroupPart = { - classes: ['no-sticky-header'], - content: groupParts - .map(groupPart => groupPart.filter(Boolean).join('\n')) - .join('\n<hr>\n'), - }; - return { - stickyMode: 'column', - multiple: [trackListPart, combinedGroupPart], - }; - } else { - return { - stickyMode: 'last', - multiple: [...groupParts, trackListPart], - }; - } } export function generateAlbumSecondaryNav(album, currentTrack, { @@ -696,174 +254,4 @@ export function generateAlbumSecondaryNav(album, currentTrack, { content: groupParts, }; } - -function checkGalleryPage(album) { - return album.tracks.some(t => t.hasUniqueCoverArt); -} - -function checkCommentaryPage(album) { - return !!album.commentary || album.tracks.some(t => t.commentary); -} - -export function generateAlbumNavLinks(album, currentTrack, { - generateNavigationLinks, - html, - language, - link, - - currentExtra = null, - showTrackNavigation = true, - showExtraLinks = null, -}) { - const isTrackPage = !!currentTrack; - - showExtraLinks ??= currentTrack ? false : true; - - const extraLinks = showExtraLinks ? [ - checkGalleryPage(album) && - link.albumGallery(album, { - class: [currentExtra === 'gallery' && 'current'], - text: language.$('albumPage.nav.gallery'), - }), - - checkCommentaryPage(album) && - link.albumCommentary(album, { - class: [currentExtra === 'commentary' && 'current'], - text: language.$('albumPage.nav.commentary'), - }), - ].filter(Boolean) : []; - - const previousNextLinks = - showTrackNavigation && - album.tracks.length > 1 && - generateNavigationLinks(currentTrack, { - data: album.tracks, - linkKey: 'track', - returnAsArray: true, - }) - - const randomLink = - showTrackNavigation && - album.tracks.length > 1 && - html.tag('a', - { - href: '#', - 'data-random': 'track-in-album', - id: 'random-button' - }, - (isTrackPage - ? language.$('trackPage.nav.random') - : language.$('albumPage.nav.randomTrack'))); - - const allLinks = [ - ...previousNextLinks || [], - ...extraLinks || [], - randomLink, - ].filter(Boolean); - - if (empty(allLinks)) { - return ''; - } - - return `(${language.formatUnitList(allLinks)})`; -} - -export function generateAlbumExtrasPageNav(album, currentExtra, { - html, - language, - link, -}) { - return { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - { - html: language.$('albumPage.nav.album', { - album: link.album(album, {class: 'current'}), - }), - }, - { - divider: false, - html: generateAlbumNavLinks(album, null, { - currentExtra, - showTrackNavigation: false, - showExtraLinks: true, - - html, - language, - link, - }), - } - ], - }; -} - -export function generateAlbumChronologyLinks(album, currentTrack, { - generateChronologyLinks, - html, -}) { - return html.tag( - 'div', - { - [html.onlyIfContent]: true, - class: 'nav-chronology-links', - }, - [ - ...html.fragment( - currentTrack && [ - ...html.fragment( - generateChronologyLinks(currentTrack, { - contribKey: 'artistContribs', - getThings: (artist) => [ - ...artist.tracksAsArtist, - ...artist.tracksAsContributor, - ], - headingString: 'misc.chronology.heading.track', - })), - - ...html.fragment( - generateChronologyLinks(currentTrack, { - contribKey: 'contributorContribs', - getThings: (artist) => [ - ...artist.tracksAsArtist, - ...artist.tracksAsContributor, - ], - headingString: 'misc.chronology.heading.track', - })), - ]), - - ...html.fragment( - generateChronologyLinks(currentTrack || album, { - contribKey: 'coverArtistContribs', - dateKey: 'coverArtDate', - getThings: (artist) => [ - ...artist.albumsAsCoverArtist, - ...artist.tracksAsCoverArtist, - ], - headingString: 'misc.chronology.heading.coverArt', - })), - ]); -} - -export function generateAlbumAdditionalFilesList(album, additionalFiles, { - fileSize = true, - - generateAdditionalFilesList, - getSizeOfAdditionalFile, - link, - urls, -}) { - return generateAdditionalFilesList(additionalFiles, { - getFileSize: - (fileSize - ? (file) => - // TODO: Kinda near the metal here... - getSizeOfAdditionalFile( - urls - .from('media.root') - .to('media.albumAdditionalFile', album.directory, file)) - : () => null), - linkFile: (file) => - link.albumAdditionalFile({album, file}), - }); -} +*/ diff --git a/src/page/artist.js b/src/page/artist.js index 4ef44d32..ad365161 100644 --- a/src/page/artist.js +++ b/src/page/artist.js @@ -2,682 +2,22 @@ // // NB: See artist-alias.js for artist alias redirect pages. -import { - bindOpts, - empty, - unique, -} from '../util/sugar.js'; - -import { - chunkByProperties, - getTotalDuration, - sortAlbumsTracksChronologically, - sortFlashesChronologically, -} from '../util/wiki-data.js'; - export const description = `per-artist info & artwork gallery pages`; export function targets({wikiData}) { return wikiData.artistData; } -export function write(artist, {wikiData}) { - const {groupData, wikiInfo} = wikiData; - - const {name, urls, contextNotes} = artist; - - const artThingsAll = sortAlbumsTracksChronologically( - unique([ - ...(artist.albumsAsCoverArtist ?? []), - ...(artist.albumsAsWallpaperArtist ?? []), - ...(artist.albumsAsBannerArtist ?? []), - ...(artist.tracksAsCoverArtist ?? []), - ]), - {getDate: (o) => o.coverArtDate}); - - const artThingsGallery = sortAlbumsTracksChronologically( - [ - ...(artist.albumsAsCoverArtist ?? []), - ...(artist.tracksAsCoverArtist ?? []), - ], - {latestFirst: true, getDate: (o) => o.coverArtDate}); - - const commentaryThings = sortAlbumsTracksChronologically([ - ...(artist.albumsAsCommentator ?? []), - ...(artist.tracksAsCommentator ?? []), - ]); - - const hasGallery = !empty(artThingsGallery); - - const getArtistsAndContrib = (thing, key) => ({ - artists: thing[key]?.filter(({who}) => who !== artist), - contrib: thing[key]?.find(({who}) => who === artist), - thing, - key, - }); - - const artListChunks = chunkByProperties( - artThingsAll.flatMap((thing) => - ['coverArtistContribs', 'wallpaperArtistContribs', 'bannerArtistContribs'] - .map((key) => getArtistsAndContrib(thing, key)) - .filter(({contrib}) => contrib) - .map((props) => ({ - album: thing.album || thing, - track: thing.album ? thing : null, - date: thing.date, - ...props, - }))), - ['date', 'album']); - - const commentaryListChunks = chunkByProperties( - commentaryThings.map((thing) => ({ - album: thing.album || thing, - track: thing.album ? thing : null, - })), - ['album']); - - const allTracks = sortAlbumsTracksChronologically( - unique([ - ...(artist.tracksAsArtist ?? []), - ...(artist.tracksAsContributor ?? []), - ])); - - const chunkTracks = (tracks) => - chunkByProperties( - tracks.map((track) => ({ - track, - date: +track.date, - album: track.album, - duration: track.duration, - originalReleaseTrack: track.originalReleaseTrack, - artists: track.artistContribs.some(({who}) => who === artist) - ? track.artistContribs.filter(({who}) => who !== artist) - : track.contributorContribs.filter(({who}) => who !== artist), - contrib: { - who: artist, - whatArray: [ - track.artistContribs.find(({who}) => who === artist)?.what, - track.contributorContribs.find(({who}) => who === artist)?.what, - ].filter(Boolean), - }, - })), - ['date', 'album']) - .map(({date, album, chunk}) => ({ - date, - album, - chunk, - duration: getTotalDuration(chunk, {originalReleasesOnly: true}), - })); - - const trackListChunks = chunkTracks(allTracks); - const totalDuration = getTotalDuration(allTracks.filter(t => !t.originalReleaseTrack)); - - 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(allTracks); - const artGroups = countGroups(artThingsAll); - - let flashes, flashListChunks; - if (wikiInfo.enableFlashesAndGames) { - flashes = sortFlashesChronologically(artist.flashesAsContributor.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.contributorContribs.find(({who}) => who === artist), - })), - ['act'] - ).map(({act, chunk}) => ({ - act, - chunk, - dateFirst: chunk[0].date, - dateLast: chunk[chunk.length - 1].date, - })); - } - - const generateEntryAccents = ({ - getArtistString, - language, - original, - entry, - artists, - contrib, - }) => - original - ? language.$('artistPage.creditList.entry.rerelease', {entry}) - : !empty(artists) - ? contrib.what || contrib.whatArray?.length - ? language.$('artistPage.creditList.entry.withArtists.withContribution', { - entry, - artists: getArtistString(artists), - contribution: contrib.whatArray - ? language.formatUnitList(contrib.whatArray) - : contrib.what, - }) - : language.$('artistPage.creditList.entry.withArtists', { - entry, - artists: getArtistString(artists), - }) - : contrib.what || contrib.whatArray?.length - ? language.$('artistPage.creditList.entry.withContribution', { - entry, - contribution: contrib.whatArray - ? language.formatUnitList(contrib.whatArray) - : contrib.what, - }) - : entry; - - const unbound_generateTrackList = (chunks, { - getArtistString, - html, - language, - link, - }) => - html.tag('dl', - chunks.flatMap(({date, album, chunk, duration}) => [ - html.tag('dt', - date && duration ? - language.$('artistPage.creditList.album.withDate.withDuration', { - album: link.album(album), - date: language.formatDate(date), - duration: language.formatDuration(duration, { - approximate: true, - }), - }) : - - date ? - language.$('artistPage.creditList.album.withDate', { - album: link.album(album), - date: language.formatDate(date), - }) : - - duration ? - language.$('artistPage.creditList.album.withDuration', { - album: link.album(album), - duration: language.formatDuration(duration, { - approximate: true, - }), - }) : - - language.$('artistPage.creditList.album', { - album: link.album(album), - })), - - html.tag('dd', - html.tag('ul', - chunk - .map(({track, ...props}) => ({ - original: track.originalReleaseTrack, - entry: language.$('artistPage.creditList.entry.track.withDuration', { - track: link.track(track), - duration: language.formatDuration(track.duration ?? 0), - }), - ...props, - })) - .map(({original, ...opts}) => - html.tag('li', - {class: original && 'rerelease'}, - generateEntryAccents({ - getArtistString, - language, - original, - ...opts, - }) - ) - ))), - ])); - - 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 jumpTo = { - tracks: !empty(allTracks), - art: !empty(artThingsAll), - flashes: wikiInfo.enableFlashesAndGames && !empty(flashes), - commentary: !empty(commentaryThings), - }; - - const showJumpTo = Object.values(jumpTo).includes(true); - - 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.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), - }, - }; - }, - }; - - const infoPage = { - type: 'page', - path: ['artist', artist.directory], - page: ({ - fancifyURL, - generateInfoGalleryLinks, - getArtistAvatar, - getArtistString, - html, - link, - language, - transformMultiline, - }) => { - const generateTrackList = bindOpts(unbound_generateTrackList, { - getArtistString, - html, - language, - link, - }); - - return { - title: language.$('artistPage.title', {artist: name}), - - cover: artist.hasAvatar && { - src: getArtistAvatar(artist), - alt: language.$('misc.alt.artistAvatar'), - }, - - main: { - headingMode: 'sticky', - - content: [ - ...html.fragment( - contextNotes && [ - html.tag('p', - language.$('releaseInfo.note')), - - html.tag('blockquote', - transformMultiline(contextNotes)), - - html.tag('hr'), - ]), - - !empty(urls) && - html.tag('p', - language.$('releaseInfo.visitOn', { - links: language.formatDisjunctionList( - urls.map((url) => fancifyURL(url, {language})) - ), - })), - - hasGallery && - html.tag('p', - language.$('artistPage.viewArtGallery', { - link: link.artistGallery(artist, { - text: language.$('artistPage.viewArtGallery.link'), - }), - })), - - showJumpTo && - html.tag('p', - language.$('misc.jumpTo.withLinks', { - links: language.formatUnitList( - [ - jumpTo.tracks && - html.tag('a', - {href: '#tracks'}, - language.$('artistPage.trackList.title')), - - jumpTo.art && - html.tag('a', - {href: '#art'}, - language.$('artistPage.artList.title')), - - jumpTo.flashes && - html.tag('a', - {href: '#flashes'}, - language.$('artistPage.flashList.title')), - - jumpTo.commentary && - html.tag('a', - {href: '#commentary'}, - language.$('artistPage.commentaryList.title')), - ].filter(Boolean)), - })), - - ...html.fragment( - !empty(allTracks) && [ - html.tag('h2', - {id: 'tracks', class: ['content-heading']}, - language.$('artistPage.trackList.title')), - - totalDuration > 0 && - html.tag('p', - language.$('artistPage.contributedDurationLine', { - artist: artist.name, - duration: language.formatDuration( - totalDuration, - { - approximate: true, - unit: true, - } - ), - })), - - !empty(musicGroups) && - html.tag('p', - language.$('artistPage.musicGroupsLine', { - groups: language.formatUnitList( - musicGroups.map(({group, contributions}) => - language.$('artistPage.groupsLine.item', { - group: link.groupInfo(group), - contributions: - language.countContributions( - contributions - ), - }) - ) - ), - })), - - generateTrackList(trackListChunks), - ]), - - ...html.fragment( - !empty(artThingsAll) && [ - html.tag('h2', - {id: 'art', class: ['content-heading']}, - language.$('artistPage.artList.title')), - - hasGallery && - html.tag('p', - language.$('artistPage.viewArtGallery.orBrowseList', { - link: link.artistGallery(artist, { - text: language.$('artistPage.viewArtGallery.link'), - }) - })), - - !empty(artGroups) && - html.tag('p', - language.$('artistPage.artGroupsLine', { - groups: language.formatUnitList( - artGroups.map(({group, contributions}) => - language.$('artistPage.groupsLine.item', { - group: link.groupInfo(group), - contributions: - language.countContributions( - contributions - ), - }) - ) - ), - })), - - html.tag('dl', - artListChunks.flatMap(({date, album, chunk}) => [ - html.tag('dt', language.$('artistPage.creditList.album.withDate', { - album: link.album(album), - date: language.formatDate(date), - })), - - html.tag('dd', - html.tag('ul', - chunk - .map(({track, key, ...props}) => ({ - ...props, - entry: - track - ? language.$('artistPage.creditList.entry.track', { - track: link.track(track), - }) - : html.tag('i', - language.$('artistPage.creditList.entry.album.' + { - wallpaperArtistContribs: - 'wallpaperArt', - bannerArtistContribs: - 'bannerArt', - coverArtistContribs: - 'coverArt', - }[key])), - })) - .map((opts) => generateEntryAccents({ - getArtistString, - language, - ...opts, - })) - .map(row => html.tag('li', row)))), - ])), - ]), - - ...html.fragment( - wikiInfo.enableFlashesAndGames && - !empty(flashes) && [ - html.tag('h2', - {id: 'flashes', class: ['content-heading']}, - language.$('artistPage.flashList.title')), - - html.tag('dl', - flashListChunks.flatMap(({ - act, - chunk, - dateFirst, - dateLast, - }) => [ - html.tag('dt', - language.$('artistPage.creditList.flashAct.withDateRange', { - act: link.flash(chunk[0].flash, { - text: act.name, - }), - dateRange: language.formatDateRange( - dateFirst, - dateLast - ), - })), - - html.tag('dd', - html.tag('ul', - chunk - .map(({flash, ...props}) => ({ - ...props, - entry: language.$('artistPage.creditList.entry.flash', { - flash: link.flash(flash), - }), - })) - .map(opts => generateEntryAccents({ - getArtistString, - language, - ...opts, - })) - .map(row => html.tag('li', row)))), - ])), - ]), - - ...html.fragment( - !empty(commentaryThings) && [ - html.tag('h2', - {id: 'commentary', class: ['content-heading']}, - language.$('artistPage.commentaryList.title')), - - html.tag('dl', - commentaryListChunks.flatMap(({album, chunk}) => [ - html.tag('dt', - language.$('artistPage.creditList.album', { - album: link.album(album), - })), - - html.tag('dd', - html.tag('ul', - chunk - .map(({track}) => track - ? language.$('artistPage.creditList.entry.track', { - track: link.track(track), - }) - : html.tag('i', - language.$('artistPage.creditList.entry.album.commentary'))) - .map(row => html.tag('li', row)))), - ])), - ]), - ], - }, - - nav: generateNavForArtist(artist, false, hasGallery, { - generateInfoGalleryLinks, - link, - language, - wikiData, - }), - }; - }, - }; - - const galleryPage = hasGallery && { - type: 'page', - path: ['artistGallery', artist.directory], - page: ({ - generateInfoGalleryLinks, - getAlbumCover, - getGridHTML, - getTrackCover, - html, - link, - language, - }) => ({ - title: language.$('artistGalleryPage.title', {artist: name}), - - main: { - classes: ['top-index'], - headingMode: 'static', - - content: [ - html.tag('p', - {class: 'quick-info'}, - language.$('artistGalleryPage.infoLine', { - coverArts: language.countCoverArts(artThingsGallery.length, { - unit: true, - }), - })), - - html.tag('div', - {class: 'grid-listing'}, - getGridHTML({ - entries: artThingsGallery.map((item) => ({item})), - srcFn: (thing) => - thing.album - ? getTrackCover(thing) - : getAlbumCover(thing), - linkFn: (thing, opts) => - thing.album - ? link.track(thing, opts) - : link.album(thing, opts), - })), - ], - }, - - nav: generateNavForArtist(artist, true, hasGallery, { - generateInfoGalleryLinks, - link, - language, - wikiData, - }), - }), - }; - - return [data, infoPage, galleryPage].filter(Boolean); -} - -// Utility functions - -function generateNavForArtist(artist, isGallery, hasGallery, { - generateInfoGalleryLinks, - language, - link, - wikiData, -}) { - const {wikiInfo} = wikiData; +export function pathsForTarget(artist) { + return [ + { + type: 'page', + path: ['artist', artist.directory], - const infoGalleryLinks = - hasGallery && - generateInfoGalleryLinks(artist, isGallery, { - link, - language, - linkKeyGallery: 'artistGallery', - linkKeyInfo: 'artist', - }); - - return { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - wikiInfo.enableListings && { - path: ['localized.listingIndex'], - title: language.$('listingIndex.title'), - }, - { - html: language.$('artistPage.nav.artist', { - artist: link.artist(artist, {class: 'current'}), - }), + contentFunction: { + name: 'generateArtistInfoPage', + args: [artist], }, - hasGallery && { - divider: false, - html: `(${infoGalleryLinks})`, - }, - ], - }; + }, + ]; } diff --git a/src/page/index.js b/src/page/index.js index f580cbea..77ebfb6f 100644 --- a/src/page/index.js +++ b/src/page/index.js @@ -2,52 +2,20 @@ // other modules here! It's not the page spec for the homepage - see // homepage.js for that. // -// Each module published in this list should follow a particular format, -// including any of the following exports: +// (TODO: The docs here from initial draft were totally outdated. +// We don't have docs for the new setup yet. +// Write those!!) // -// condition({wikiData}) -// Returns a boolean indicating whether to process targets/writes (true) or -// skip this page spec altogether (false). This is usually used for -// selectively toggling pages according to site feature flags, though it may -// also be used to e.g. skip out if no targets would be found (preventing -// writeTargetless from generating an empty index page). -// -// targets({wikiData}) -// Gets the objects which this page's write() function should be called on. -// Usually this will simply mean returning the appropriate thingData array, -// but it may also apply filter/map/etc if useful. -// -// write(thing, {wikiData}) -// Provides descriptors for any page and data writes associated with the -// given thing (which will be a value from the targets() array). This -// includes page (HTML) writes, data (JSON) writes, etc. Notably, this -// function does not perform any file operations itself; it only describes -// the operations which will be processed elsewhere, once for each -// translation language. The write function also immediately transforms -// any data which will be reused across writes of the same page, so that -// this data is effectively cached (rather than recalculated for each -// language/write). -// -// writeTargetless({wikiData}) -// Provides descriptors for page/data/etc writes which will be used -// without concern for targets. This is usually used for writing index pages -// which should be generated just once (rather than corresponding to -// targets). -// -// As these modules are effectively the HTML templates for all site layout, -// common patterns may also be exported alongside the special exports above. -// These functions should be referenced only from adjacent modules, as they -// pertain only to site page generation. export * as album from './album.js'; -export * as albumCommentary from './album-commentary.js'; +// export * as albumCommentary from './album-commentary.js'; export * as artist from './artist.js'; -export * as artistAlias from './artist-alias.js'; -export * as flash from './flash.js'; -export * as group from './group.js'; -export * as homepage from './homepage.js'; -export * as listing from './listing.js'; -export * as news from './news.js'; +// export * as artistAlias from './artist-alias.js'; +// export * as flash from './flash.js'; +// export * as group from './group.js'; +// export * as homepage from './homepage.js'; +// export * as listing from './listing.js'; +// export * as news from './news.js'; export * as static from './static.js'; -export * as tag from './tag.js'; +// export * as tag from './tag.js'; export * as track from './track.js'; diff --git a/src/page/static.js b/src/page/static.js index 8572db4e..82330dec 100644 --- a/src/page/static.js +++ b/src/page/static.js @@ -8,26 +8,16 @@ export function targets({wikiData}) { return wikiData.staticPageData; } -export function write(staticPage) { - const page = { - type: 'page', - path: ['staticPage', staticPage.directory], - page: ({ - transformMultiline, - }) => ({ - title: staticPage.name, - stylesheet: staticPage.stylesheet, +export function pathsForTarget(staticPage) { + return [ + { + type: 'page', + path: ['staticPage', staticPage.directory], - main: { - classes: ['long-content'], - headingMode: 'sticky', - - content: transformMultiline(staticPage.content), + contentFunction: { + name: 'generateStaticPage', + args: [staticPage], }, - - nav: {simple: true}, - }), - }; - - return [page]; + }, + ]; } diff --git a/src/page/track.js b/src/page/track.js index b6b03f35..e75b6958 100644 --- a/src/page/track.js +++ b/src/page/track.js @@ -1,553 +1,21 @@ // Track page specification. -import { - generateAlbumChronologyLinks, - generateAlbumNavLinks, - generateAlbumSecondaryNav, - generateAlbumSidebar, - generateAlbumAdditionalFilesList as unbound_generateAlbumAdditionalFilesList, -} from './album.js'; - -import { - bindOpts, - empty, -} from '../util/sugar.js'; - -import { - getTrackCover, - getAlbumListTag, - sortFlashesChronologically, -} from '../util/wiki-data.js'; - export const description = `per-track info pages`; export function targets({wikiData}) { return wikiData.trackData; } -export function write(track, {wikiData}) { - const {wikiInfo} = wikiData; - - const { - album, - contributorContribs, - referencedByTracks, - referencedTracks, - sampledByTracks, - sampledTracks, - otherReleases, - } = track; - - const listTag = getAlbumListTag(album); - - let flashesThatFeature; - if (wikiInfo.enableFlashesAndGames) { - flashesThatFeature = sortFlashesChronologically( - [track, ...otherReleases].flatMap((track) => - track.featuredInFlashes.map((flash) => ({ - flash, - as: track, - directory: flash.directory, - name: flash.name, - date: flash.date, - })) - ) - ); - } - - const unbound_getTrackItem = (track, { - getArtistString, - html, - language, - link, - }) => - html.tag('li', - language.$('trackList.item.withArtists', { - track: link.track(track), - by: html.tag('span', - {class: 'by'}, - language.$('trackList.item.withArtists.by', { - artists: getArtistString(track.artistContribs), - })), - })); - - const hasCommentary = - track.commentary || otherReleases.some((t) => t.commentary); +export function pathsForTarget(track) { + return [ + { + type: 'page', + path: ['track', track.directory], - const hasAdditionalFiles = !empty(track.additionalFiles); - const hasSheetMusicFiles = !empty(track.sheetMusicFiles); - const hasMidiProjectFiles = !empty(track.midiProjectFiles); - const numAdditionalFiles = album.additionalFiles.flatMap((g) => g.files).length; - - const generateCommentary = ({language, link, transformMultiline}) => - transformMultiline([ - track.commentary, - ...otherReleases.map((track) => - track.commentary - ?.split('\n') - .filter((line) => line.replace(/<\/b>/g, '').includes(':</i>')) - .flatMap(line => [ - line, - language.$('releaseInfo.artistCommentary.seeOriginalRelease', { - original: link.track(track), - }), - ]) - .join('\n') - ), - ].filter(Boolean).join('\n')); - - const data = { - type: 'data', - path: ['track', track.directory], - data: ({ - serializeContribs, - serializeCover, - serializeGroupsForTrack, - serializeLink, - }) => ({ - name: track.name, - directory: track.directory, - dates: { - released: track.date, - originallyReleased: track.originalDate, - coverArtAdded: track.coverArtDate, + contentFunction: { + name: 'generateTrackInfoPage', + args: [track], }, - duration: track.duration, - color: track.color, - cover: serializeCover(track, getTrackCover), - artistsContribs: serializeContribs(track.artistContribs), - contributorContribs: serializeContribs(track.contributorContribs), - coverArtistContribs: serializeContribs(track.coverArtistContribs || []), - album: serializeLink(track.album), - groups: serializeGroupsForTrack(track), - references: track.references.map(serializeLink), - referencedBy: track.referencedBy.map(serializeLink), - alsoReleasedAs: otherReleases.map((track) => ({ - track: serializeLink(track), - album: serializeLink(track.album), - })), - }), - }; - - const getSocialEmbedDescription = ({ - getArtistString: _getArtistString, - language, - }) => { - const hasArtists = !empty(track.artistContribs); - const hasCoverArtists = !empty(track.coverArtistContribs); - const getArtistString = (contribs) => - _getArtistString(contribs, { - // We don't want to put actual HTML tags in social embeds (sadly - // they don't get parsed and displayed, generally speaking), so - // override the link argument so that artist "links" just show - // their names. - link: {artist: (artist) => artist.name}, - }); - if (!hasArtists && !hasCoverArtists) return ''; - return language.formatString( - 'trackPage.socialEmbed.body' + - [hasArtists && '.withArtists', hasCoverArtists && '.withCoverArtists'] - .filter(Boolean) - .join(''), - Object.fromEntries( - [ - hasArtists && ['artists', getArtistString(track.artistContribs)], - hasCoverArtists && [ - 'coverArtists', - getArtistString(track.coverArtistContribs), - ], - ].filter(Boolean) - ) - ); - }; - - const page = { - type: 'page', - path: ['track', track.directory], - page: ({ - absoluteTo, - fancifyURL, - generateAdditionalFilesList, - generateAdditionalFilesShortcut, - generateChronologyLinks, - generateContentHeading, - generateNavigationLinks, - generateTrackListDividedByGroups, - getAlbumStylesheet, - getArtistString, - getLinkThemeString, - getSizeOfAdditionalFile, - getThemeString, - getTrackCover, - html, - link, - language, - transformLyrics, - transformMultiline, - to, - urls, - }) => { - const getTrackItem = bindOpts(unbound_getTrackItem, { - getArtistString, - html, - language, - link, - }); - - const generateAlbumAdditionalFilesList = bindOpts(unbound_generateAlbumAdditionalFilesList, { - [bindOpts.bindIndex]: 2, - generateAdditionalFilesList, - getSizeOfAdditionalFile, - link, - urls, - }); - - return { - title: language.$('trackPage.title', {track: track.name}), - stylesheet: getAlbumStylesheet(album, {to}), - - themeColor: track.color, - theme: - getThemeString(track.color, { - additionalVariables: [ - `--album-directory: ${album.directory}`, - `--track-directory: ${track.directory}`, - ] - }), - - socialEmbed: { - heading: language.$('trackPage.socialEmbed.heading', { - album: track.album.name, - }), - headingLink: absoluteTo('localized.album', album.directory), - title: language.$('trackPage.socialEmbed.title', { - track: track.name, - }), - description: getSocialEmbedDescription({getArtistString, language}), - image: '/' + getTrackCover(track, {to: urls.from('shared.root').to}), - color: track.color, - }, - - // disabled for now! shifting banner position per height of page is disorienting - /* - banner: !empty(album.bannerArtistContribs) && { - classes: ['dim'], - dimensions: album.bannerDimensions, - path: ['media.albumBanner', album.directory, album.bannerFileExtension], - alt: language.$('misc.alt.albumBanner'), - position: 'bottom' - }, - */ - - cover: { - src: getTrackCover(track), - alt: language.$('misc.alt.trackCover'), - artTags: track.artTags, - }, - - main: { - headingMode: 'sticky', - - content: [ - html.tag('p', - { - [html.onlyIfContent]: true, - [html.joinChildren]: '<br>', - }, - [ - !empty(track.artistContribs) && - language.$('releaseInfo.by', { - artists: getArtistString(track.artistContribs, { - showContrib: true, - showIcons: true, - }), - }), - - !empty(track.coverArtistContribs) && - language.$('releaseInfo.coverArtBy', { - artists: getArtistString(track.coverArtistContribs, { - showContrib: true, - showIcons: true, - }), - }), - - track.date && - language.$('releaseInfo.released', { - date: language.formatDate(track.date), - }), - - track.hasCoverArt && - track.coverArtDate && - +track.coverArtDate !== +track.date && - language.$('releaseInfo.artReleased', { - date: language.formatDate(track.coverArtDate), - }), - - track.duration && - language.$('releaseInfo.duration', { - duration: language.formatDuration( - track.duration - ), - }), - ]), - - html.tag('p', - { - [html.onlyIfContent]: true, - [html.joinChildren]: '<br>', - }, - [ - hasSheetMusicFiles && - language.$('releaseInfo.sheetMusicFiles.shortcut', { - link: html.tag('a', - {href: '#sheet-music-files'}, - language.$('releaseInfo.sheetMusicFiles.shortcut.link')), - }), - - hasMidiProjectFiles && - language.$('releaseInfo.midiProjectFiles.shortcut', { - link: html.tag('a', - {href: '#midi-project-files'}, - language.$('releaseInfo.midiProjectFiles.shortcut.link')), - }), - - hasAdditionalFiles && - generateAdditionalFilesShortcut(track.additionalFiles), - ]), - - html.tag('p', - (empty(track.urls) - ? language.$('releaseInfo.listenOn.noLinks') - : language.$('releaseInfo.listenOn', { - links: language.formatDisjunctionList( - track.urls.map(url => fancifyURL(url, {language}))), - }))), - - ...html.fragment( - !empty(otherReleases) && [ - generateContentHeading({ - id: 'also-released-as', - title: language.$('releaseInfo.alsoReleasedAs'), - }), - - html.tag('ul', otherReleases.map(track => - html.tag('li', language.$('releaseInfo.alsoReleasedAs.item', { - track: link.track(track), - album: link.album(track.album), - })))), - ]), - - ...html.fragment( - !empty(contributorContribs) && [ - generateContentHeading({ - id: 'contributors', - title: language.$('releaseInfo.contributors'), - }), - - html.tag('ul', contributorContribs.map(contrib => - html.tag('li', getArtistString([contrib], { - showContrib: true, - showIcons: true, - })))), - ]), - - ...html.fragment( - !empty(referencedTracks) && [ - generateContentHeading({ - id: 'references', - title: - language.$('releaseInfo.tracksReferenced', { - track: html.tag('i', track.name), - }), - }), - - html.tag('ul', referencedTracks.map(getTrackItem)), - ]), - - ...html.fragment( - !empty(referencedByTracks) && [ - generateContentHeading({ - id: 'referenced-by', - title: - language.$('releaseInfo.tracksThatReference', { - track: html.tag('i', track.name), - }), - }), - - generateTrackListDividedByGroups(referencedByTracks, { - getTrackItem, - wikiData, - }), - ]), - - ...html.fragment( - !empty(sampledTracks) && [ - generateContentHeading({ - id: 'samples', - title: - language.$('releaseInfo.tracksSampled', { - track: html.tag('i', track.name), - }), - }), - - html.tag('ul', sampledTracks.map(getTrackItem)), - ]), - - ...html.fragment( - !empty(sampledByTracks) && [ - generateContentHeading({ - id: 'sampled-by', - title: - language.$('releaseInfo.tracksThatSample', { - track: html.tag('i', track.name), - }) - }), - - html.tag('ul', sampledByTracks.map(getTrackItem)), - ]), - - ...html.fragment( - wikiInfo.enableFlashesAndGames && - !empty(flashesThatFeature) && [ - generateContentHeading({ - id: 'featured-in', - title: - language.$('releaseInfo.flashesThatFeature', { - track: html.tag('i', track.name), - }), - }), - - html.tag('ul', flashesThatFeature.map(({flash, as}) => - html.tag('li', - {class: as !== track && 'rerelease'}, - (as === track - ? language.$('releaseInfo.flashesThatFeature.item', { - flash: link.flash(flash), - }) - : language.$('releaseInfo.flashesThatFeature.item.asDifferentRelease', { - flash: link.flash(flash), - track: link.track(as), - }))))), - ]), - - ...html.fragment( - track.lyrics && [ - generateContentHeading({ - id: 'lyrics', - title: language.$('releaseInfo.lyrics'), - }), - - html.tag('blockquote', transformLyrics(track.lyrics)), - ]), - - ...html.fragment( - hasSheetMusicFiles && [ - generateContentHeading({ - id: 'sheet-music-files', - title: language.$('releaseInfo.sheetMusicFiles.heading'), - }), - - generateAlbumAdditionalFilesList(album, track.sheetMusicFiles, { - fileSize: false, - }), - ]), - - ...html.fragment( - hasMidiProjectFiles && [ - generateContentHeading({ - id: 'midi-project-files', - title: language.$('releaseInfo.midiProjectFiles.heading'), - }), - - generateAlbumAdditionalFilesList(album, track.midiProjectFiles), - ]), - - ...html.fragment( - hasAdditionalFiles && [ - generateContentHeading({ - id: 'additional-files', - title: language.$('releaseInfo.additionalFiles.heading', { - additionalFiles: language.countAdditionalFiles(numAdditionalFiles, { - unit: true, - }), - }) - }), - - generateAlbumAdditionalFilesList(album, track.additionalFiles), - ]), - - ...html.fragment( - hasCommentary && [ - generateContentHeading({ - id: 'artist-commentary', - title: language.$('releaseInfo.artistCommentary'), - }), - - html.tag('blockquote', generateCommentary({ - link, - language, - transformMultiline, - })), - ]), - ], - }, - - sidebarLeft: generateAlbumSidebar(album, track, { - fancifyURL, - getLinkThemeString, - html, - language, - link, - transformMultiline, - wikiData, - }), - - nav: { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - { - path: ['localized.album', album.directory], - title: album.name, - }, - listTag === 'ol' && - { - html: language.$('trackPage.nav.track.withNumber', { - number: album.tracks.indexOf(track) + 1, - track: link.track(track, {class: 'current', to}), - }), - }, - listTag === 'ul' && - { - html: language.$('trackPage.nav.track', { - track: link.track(track, {class: 'current', to}), - }), - }, - ].filter(Boolean), - - content: generateAlbumChronologyLinks(album, track, { - generateChronologyLinks, - html, - }), - - bottomRowContent: - album.tracks.length > 1 && - generateAlbumNavLinks(album, track, { - generateNavigationLinks, - html, - language, - }), - }, - - secondaryNav: generateAlbumSecondaryNav(album, track, { - getLinkThemeString, - html, - language, - link, - }), - }; }, - }; - - return [data, page]; + ]; } |