summaryrefslogtreecommitdiff
path: root/src/page
diff options
context:
space:
mode:
author(quasar) nebula <towerofnix@gmail.com>2021-06-01 15:32:03 -0300
committer(quasar) nebula <towerofnix@gmail.com>2021-06-01 15:32:03 -0300
commit234747721fec14e69fc75d6c0134ad4a5ae7736e (patch)
tree2f478d474ee0a0e0d009d7bc39589e89da39c181 /src/page
parent76207fff8bd19d443242ceb841aba09d2fc24190 (diff)
basic module-ify album pages
Other pages are commented out for now. Also, this doesn't include the source .txt processing functions yet, 8ut that'll pro8a8ly end up in the page/ files too.
Diffstat (limited to 'src/page')
-rw-r--r--src/page/album.js381
-rw-r--r--src/page/index.js5
2 files changed, 386 insertions, 0 deletions
diff --git a/src/page/album.js b/src/page/album.js
new file mode 100644
index 0000000..f859779
--- /dev/null
+++ b/src/page/album.js
@@ -0,0 +1,381 @@
+// Album page specification.
+//
+// Also exports utility functions:
+// - generateAlbumSidebar
+// - generateAlbumNavLinks
+// - generateAlbumChronologyLinks
+
+import fixWS from 'fix-whitespace';
+
+import {
+ getAlbumCover,
+ getAlbumListTag,
+ getTotalDuration
+} from '../util/wiki-data.js';
+
+import {
+ getLinkThemeString,
+ getThemeString
+} from '../util/colors.js';
+
+import * as html from '../util/html.js';
+
+export function targets({wikiData}) {
+ return wikiData.albumData;
+}
+
+export function write(album, {wikiData}) {
+ const { wikiInfo } = wikiData;
+
+ const trackToListItem = (track, {getArtistString, link, strings}) => {
+ const itemOpts = {
+ duration: strings.count.duration(track.duration),
+ track: link.track(track)
+ };
+ return `<li style="${getLinkThemeString(track.color)}">${
+ (track.artists === album.artists
+ ? strings('trackList.item.withDuration', itemOpts)
+ : strings('trackList.item.withDuration.withArtists', {
+ ...itemOpts,
+ by: `<span class="by">${
+ strings('trackList.item.withArtists.by', {
+ artists: getArtistString(track.artists)
+ })
+ }</span>`
+ }))
+ }</li>`;
+ };
+
+ const commentaryEntries = [album, ...album.tracks].filter(x => x.commentary).length;
+ const albumDuration = getTotalDuration(album.tracks);
+
+ 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.dateAdded
+ },
+ duration: albumDuration,
+ color: album.color,
+ cover: serializeCover(album, getAlbumCover),
+ artists: serializeContribs(album.artists || []),
+ coverArtists: serializeContribs(album.coverArtists || []),
+ wallpaperArtists: serializeContribs(album.wallpaperArtists || []),
+ bannerArtists: serializeContribs(album.bannerArtists || []),
+ 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: ({
+ chronologyLinks,
+ fancifyURL,
+ generateCoverLink,
+ getAlbumStylesheet,
+ getArtistString,
+ link,
+ strings,
+ transformMultiline
+ }) => ({
+ title: strings('albumPage.title', {album: album.name}),
+ stylesheet: getAlbumStylesheet(album),
+ theme: getThemeString(album.color, [
+ `--album-directory: ${album.directory}`
+ ]),
+
+ banner: album.bannerArtists && {
+ dimensions: album.bannerDimensions,
+ path: ['media.albumBanner', album.directory],
+ alt: strings('misc.alt.albumBanner'),
+ position: 'top'
+ },
+
+ main: {
+ content: fixWS`
+ ${generateCoverLink({
+ path: ['media.albumCover', album.directory],
+ alt: strings('misc.alt.albumCover'),
+ tags: album.artTags
+ })}
+ <h1>${strings('albumPage.title', {album: album.name})}</h1>
+ <p>
+ ${[
+ album.artists && strings('releaseInfo.by', {
+ artists: getArtistString(album.artists, {
+ showContrib: true,
+ showIcons: true
+ })
+ }),
+ album.coverArtists && strings('releaseInfo.coverArtBy', {
+ artists: getArtistString(album.coverArtists, {
+ showContrib: true,
+ showIcons: true
+ })
+ }),
+ album.wallpaperArtists && strings('releaseInfo.wallpaperArtBy', {
+ artists: getArtistString(album.wallpaperArtists, {
+ showContrib: true,
+ showIcons: true
+ })
+ }),
+ album.bannerArtists && strings('releaseInfo.bannerArtBy', {
+ artists: getArtistString(album.bannerArtists, {
+ showContrib: true,
+ showIcons: true
+ })
+ }),
+ strings('releaseInfo.released', {
+ date: strings.count.date(album.date)
+ }),
+ +album.coverArtDate !== +album.date && strings('releaseInfo.artReleased', {
+ date: strings.count.date(album.coverArtDate)
+ }),
+ strings('releaseInfo.duration', {
+ duration: strings.count.duration(albumDuration, {approximate: album.tracks.length > 1})
+ })
+ ].filter(Boolean).join('<br>\n')}
+ </p>
+ ${commentaryEntries && `<p>${
+ strings('releaseInfo.viewCommentary', {
+ link: link.albumCommentary(album, {
+ text: strings('releaseInfo.viewCommentary.link')
+ })
+ })
+ }</p>`}
+ ${album.urls.length && `<p>${
+ strings('releaseInfo.listenOn', {
+ links: strings.list.or(album.urls.map(url => fancifyURL(url, {album: true})))
+ })
+ }</p>`}
+ ${album.trackGroups ? fixWS`
+ <dl class="album-group-list">
+ ${album.trackGroups.map(({ name, color, startIndex, tracks }) => fixWS`
+ <dt>${
+ strings('trackList.group', {
+ duration: strings.count.duration(getTotalDuration(tracks), {approximate: tracks.length > 1}),
+ group: name
+ })
+ }</dt>
+ <dd><${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}>
+ ${tracks.map(t => trackToListItem(t, {getArtistString, link, strings})).join('\n')}
+ </${listTag}></dd>
+ `).join('\n')}
+ </dl>
+ ` : fixWS`
+ <${listTag}>
+ ${album.tracks.map(t => trackToListItem(t, {getArtistString, link, strings})).join('\n')}
+ </${listTag}>
+ `}
+ <p>
+ ${[
+ strings('releaseInfo.addedToWiki', {
+ date: strings.count.date(album.dateAdded)
+ })
+ ].filter(Boolean).join('<br>\n')}
+ </p>
+ ${album.commentary && fixWS`
+ <p>${strings('releaseInfo.artistCommentary')}</p>
+ <blockquote>
+ ${transformMultiline(album.commentary)}
+ </blockquote>
+ `}
+ `
+ },
+
+ sidebarLeft: generateAlbumSidebar(album, null, {
+ fancifyURL,
+ link,
+ strings,
+ transformMultiline,
+ wikiData
+ }),
+
+ nav: {
+ links: [
+ {toHome: true},
+ {
+ html: strings('albumPage.nav.album', {
+ album: link.album(album, {class: 'current'})
+ })
+ },
+ album.tracks.length > 1 &&
+ {
+ divider: false,
+ html: generateAlbumNavLinks(album, null, {link, strings})
+ }
+ ],
+ content: html.tag('div', generateAlbumChronologyLinks(album, null, {chronologyLinks}))
+ }
+ })
+ };
+
+ return [page, data];
+}
+
+export function generateAlbumSidebar(album, currentTrack, {
+ fancifyURL,
+ link,
+ strings,
+ transformMultiline,
+ wikiData
+}) {
+ const listTag = getAlbumListTag(album);
+
+ const trackGroups = album.trackGroups || [{
+ name: strings('albumSidebar.trackList.fallbackGroupName'),
+ color: album.color,
+ startIndex: 0,
+ tracks: album.tracks
+ }];
+
+ const trackToListItem = track => html.tag('li',
+ {class: track === currentTrack && 'current'},
+ strings('albumSidebar.trackList.item', {
+ track: link.track(track)
+ }));
+
+ const trackListPart = fixWS`
+ <h1>${link.album(album)}</h1>
+ ${trackGroups.map(({ name, color, startIndex, tracks }) =>
+ 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'
+ ? strings('albumSidebar.trackList.group.withRange', {
+ group: `<span class="group-name">${name}</span>`,
+ range: `${startIndex + 1}&ndash;${startIndex + tracks.length}`
+ })
+ : strings('albumSidebar.trackList.group', {
+ group: `<span class="group-name">${name}</span>`
+ }))
+ ),
+ fixWS`
+ <${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}>
+ ${tracks.map(trackToListItem).join('\n')}
+ </${listTag}>
+ `
+ ])).join('\n')}
+ `;
+
+ const { groups } = album;
+
+ const groupParts = groups.map(group => {
+ const index = group.albums.indexOf(album);
+ const next = group.albums[index + 1];
+ const previous = group.albums[index - 1];
+ return {group, next, previous};
+ }).map(({group, next, previous}) => fixWS`
+ <h1>${
+ strings('albumSidebar.groupBox.title', {
+ group: link.groupInfo(group)
+ })
+ }</h1>
+ ${!currentTrack && transformMultiline(group.descriptionShort)}
+ ${group.urls.length && `<p>${
+ strings('releaseInfo.visitOn', {
+ links: strings.list.or(group.urls.map(url => fancifyURL(url)))
+ })
+ }</p>`}
+ ${!currentTrack && fixWS`
+ ${next && `<p class="group-chronology-link">${
+ strings('albumSidebar.groupBox.next', {
+ album: link.album(next)
+ })
+ }</p>`}
+ ${previous && `<p class="group-chronology-link">${
+ strings('albumSidebar.groupBox.previous', {
+ album: link.album(previous)
+ })
+ }</p>`}
+ `}
+ `);
+
+ 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
+ };
+ }
+}
+
+export function generateAlbumNavLinks(album, currentTrack, {link, strings}) {
+ if (album.tracks.length <= 1) {
+ return '';
+ }
+
+ const previousNextLinks = currentTrack && generatePreviousNextLinks(currentTrack, {
+ link, strings,
+ data: album.tracks,
+ linkKey: 'track'
+ });
+ const randomLink = `<a href="#" data-random="track-in-album" id="random-button">${
+ (currentTrack
+ ? strings('trackPage.nav.random')
+ : strings('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, {chronologyLinks}) {
+ return [
+ currentTrack && chronologyLinks(currentTrack, {
+ contribKey: 'artists',
+ getThings: artist => [...artist.tracks.asArtist, ...artist.tracks.asContributor],
+ headingString: 'misc.chronology.heading.track'
+ }),
+ chronologyLinks(currentTrack || album, {
+ contribKey: 'coverArtists',
+ getThings: artist => [...artist.albums.asCoverArtist, ...artist.tracks.asCoverArtist],
+ headingString: 'misc.chronology.heading.coverArt'
+ })
+ ].filter(Boolean).join('\n');
+}
diff --git a/src/page/index.js b/src/page/index.js
new file mode 100644
index 0000000..ca78238
--- /dev/null
+++ b/src/page/index.js
@@ -0,0 +1,5 @@
+// NB: This is the index for the page/ directory and contains exports for all
+// other modules here! It's not the page spec for the homepage - see
+// homepage.js for that.
+
+export * as album from './album.js';