diff options
Diffstat (limited to 'src/content')
5 files changed, 415 insertions, 186 deletions
diff --git a/src/content/dependencies/generateArtistInfoPage.js b/src/content/dependencies/generateArtistInfoPage.js index 888da2f4..19cc2617 100644 --- a/src/content/dependencies/generateArtistInfoPage.js +++ b/src/content/dependencies/generateArtistInfoPage.js @@ -1,14 +1,9 @@ -import {empty, filterProperties, unique} from '../../util/sugar.js'; - -import { - chunkByProperties, - getTotalDuration, - sortAlbumsTracksChronologically, - sortFlashesChronologically, -} from '../../util/wiki-data.js'; +import {empty, unique} from '../../util/sugar.js'; +import {getTotalDuration} from '../../util/wiki-data.js'; export default { contentDependencies: [ + 'generateArtistInfoPageTracksChunkedList', 'generateArtistNavLinks', 'generateContentHeading', 'generateCoverArtwork', @@ -41,61 +36,7 @@ export default { relations.artistNavLinks = relation('generateArtistNavLinks', artist); - function getContributionDescriptions(...contribArrays) { - const ownContribs = - contribArrays - .map(contribs => contribs.find(({who}) => who === artist)) - .filter(Boolean); - - const contributionDescriptions = - ownContribs - .map(({what}) => what) - .filter(Boolean); - - if (empty(contributionDescriptions)) { - return {}; - } - - return {contributionDescriptions}; - } - - function getOtherArtistLinks(...contribArrays) { - const otherArtistContribs = - contribArrays - .map(contribs => contribs.filter(({who}) => who !== artist)) - .flat(); - - if (empty(otherArtistContribs)) { - return {}; - } - - const otherArtistLinks = - otherArtistContribs - .map(({who}) => relation('linkArtist', who)); - - return {otherArtistLinks}; - } - - function sortContributionEntries(entries, sortFunction) { - const things = unique(entries.map(({thing}) => thing)); - sortFunction(things); - - const outputArrays = []; - const thingToOutputArray = new Map(); - - for (const thing of things) { - const array = []; - thingToOutputArray.set(thing, array); - outputArrays.push(array); - } - - for (const entry of entries) { - thingToOutputArray.get(entry.thing).push(entry); - } - - entries.splice(0, entries.length, ...outputArrays.flat()); - } - + /* function getGroupInfo(entries) { const allGroups = new Set(); const groupToDuration = new Map(); @@ -122,6 +63,7 @@ export default { return groupInfo; } + */ if (artist.hasAvatar) { relations.cover = @@ -140,50 +82,25 @@ export default { relation('linkExternal', url)); } - const trackContributionEntries = [ - ...artist.tracksAsArtist.map(track => ({ - date: track.date, - thing: track, - album: track.album, - duration: track.duration, - rerelease: track.originalReleaseTrack !== null, - trackLink: relation('linkTrack', track), - ...getContributionDescriptions(track.artistContribs), - ...getOtherArtistLinks(track.artistContribs), - })), - - ...artist.tracksAsContributor.map(track => ({ - date: track.date, - thing: track, - album: track.album, - duration: track.duration, - rerelease: track.originalReleaseTrack !== null, - trackLink: relation('linkTrack', track), - ...getContributionDescriptions(track.contributorContribs), - ...getOtherArtistLinks(track.contributorContribs), - })), - ]; - - sortContributionEntries(trackContributionEntries, sortAlbumsTracksChronologically); + if (!empty(artist.tracksAsArtist) || !empty(artist.tracksAsContributor)) { + const tracks = sections.tracks = {}; + tracks.heading = relation('generateContentHeading'); + tracks.list = relation('generateArtistInfoPageTracksChunkedList', artist); + } + /* const trackContributionChunks = - chunkByProperties(trackContributionEntries, ['album', 'date']) - .map(({album, date, chunk}) => ({ - albumLink: relation('linkAlbum', album), - date: +date, - duration: getTotalDuration(chunk), - entries: chunk - .map(entry => - filterProperties(entry, [ - 'contributionDescriptions', - 'duration', - 'otherArtistLinks', - 'rerelease', - 'trackLink', - ])), - })); - - const trackGroupInfo = getGroupInfo(trackContributionEntries, 'duration'); + query.trackContributionChunks.map(({album, chunk}) => ({ + albumLink: relation('linkAlbum', album), + entries: + chunk.map(entry => ({ + // ...getContributionDescription(entry.contribs), + ...getOtherArtistLinks(entry.contribs), + trackLink: relation('linkTrack', entry.track), + })), + })); + + const trackGroupInfo = getGroupInfo(query.trackContributionEntries, 'duration'); if (!empty(trackContributionChunks)) { const tracks = sections.tracks = {}; @@ -202,7 +119,7 @@ export default { date: album.coverArtDate, thing: album, album: album, - ...getContributionDescriptions(album.coverArtistContribs), + // ...getContributionDescription(album.coverArtistContribs), ...getOtherArtistLinks(album.coverArtistContribs), })), @@ -211,7 +128,7 @@ export default { date: album.coverArtDate, thing: album, album: album, - ...getContributionDescriptions(album.wallpaperArtistContribs), + // ...getContributionDescription(album.wallpaperArtistContribs), ...getOtherArtistLinks(album.wallpaperArtistContribs), })), @@ -220,7 +137,7 @@ export default { date: album.coverArtDate, thing: album, album: album, - ...getContributionDescriptions(album.bannerArtistContribs), + // ...getContributionDescription(album.bannerArtistContribs), ...getOtherArtistLinks(album.bannerArtistContribs), })), @@ -231,7 +148,7 @@ export default { album: track.album, rerelease: track.originalReleaseTrack !== null, trackLink: relation('linkTrack', track), - ...getContributionDescriptions(track.coverArtistContribs), + // ...getContributionDescription(track.coverArtistContribs), ...getOtherArtistLinks(track.coverArtistContribs), })), ]; @@ -246,7 +163,7 @@ export default { entries: chunk.map(entry => filterProperties(entry, [ - 'contributionDescriptions', + 'contributionDescription', 'kind', 'otherArtistLinks', 'rerelease', @@ -287,7 +204,7 @@ export default { thing: flash, act: flash.act, flashLink: relation('linkFlash', flash), - ...getContributionDescriptions(flash.contributorContribs), + // ...getContributionDescription(flash.contributorContribs), })), ]; @@ -303,7 +220,7 @@ export default { entries: chunk.map(entry => filterProperties(entry, [ - 'contributionDescriptions', + 'contributionDescription', 'flashLink', ])), })); @@ -314,7 +231,9 @@ export default { flashes.chunks = flashChunks; } } + */ + /* // Commentary doesn't use the detailed contribution system where multiple // artists are collaboratively credited for the same piece, so there isn't // really anything special to do for processing or presenting it. @@ -358,6 +277,7 @@ export default { commentary.heading = relation('generateContentHeading'); commentary.chunks = commentaryChunks; } + */ return relations; }, @@ -376,65 +296,38 @@ export default { data.totalTrackCount = allTracks.length; data.totalDuration = getTotalDuration(allTracks, {originalReleasesOnly: true}); - return data; - }, - - generate(data, relations, {html, language}) { - const {sections: sec} = relations; - - function addAccentsToEntry({ - rerelease, - entry, - otherArtistLinks, - contributionDescriptions, - }) { - if (rerelease) { - return language.$('artistPage.creditList.entry.rerelease', {entry}); - } + /* + data.trackContributionInfo = + query.trackContributionChunks + .map(({date, chunk}) => ({ + date: +date, + duration: accumulateSum(chunk, ({track}) => track.duration), + tracks: chunk.map(({track, contribs}) => ({ + ...getContributionDescription(contribs), + rerelease: track.originalReleaseTrack !== null, + duration: track.duration, + })) + })) + */ - const options = {entry}; - const parts = ['artistPage.creditList.entry']; + return data; - if (otherArtistLinks) { - parts.push('withArtists'); - options.artists = language.formatConjunctionList(otherArtistLinks); - } + /* + function getContributionDescription(contribs) { + const ownContrib = + contribs.find(({who}) => who === artist); - if (contributionDescriptions) { - parts.push('withContribution'); - options.contribution = language.formatUnitList(contributionDescriptions); - } - - if (parts.length === 1) { - return entry; + if (!ownContrib) { + return {}; } - return language.formatString(parts.join('.'), options); + return {contributionDescription: ownContrib.what}; } + */ + }, - function addAccentsToAlbumLink({ - albumLink, - date, - duration, - entries, - }) { - const options = {album: albumLink}; - const parts = ['artistPage.creditList.album']; - - if (date) { - parts.push('withDate'); - options.date = language.formatDate(new Date(date)); - } - - if (duration) { - parts.push('withDuration'); - options.duration = language.formatDuration(duration, { - approximate: entries.length > 1, - }); - } - - return language.formatString(parts.join('.'), options); - } + generate(data, relations, {html, language}) { + const {sections: sec} = relations; return relations.layout .slots({ @@ -536,31 +429,60 @@ export default { })))), })), - html.tag('dl', - sec.tracks.chunks.map(({albumLink, date, duration, entries}) => [ - html.tag('dt', - addAccentsToAlbumLink({albumLink, date, duration, entries})), + sec.tracks.list, - html.tag('dd', - html.tag('ul', - entries - .map(({trackLink, duration, ...properties}) => ({ - entry: - (duration - ? language.$('artistPage.creditList.entry.track.withDuration', { - track: trackLink, - duration: language.formatDuration(duration), - }) - : language.$('artistPage.creditList.entry.track', { - track: trackLink, - })), - ...properties, - })) - .map(addAccentsToEntry) - .map(entry => html.tag('li', entry)))), - ])), + /* + html.tag('dl', + stitchArrays({ + chunkAlbumLink: relations.sections.tracks.chunkAlbumLink, + trackLinks: relations.sections.tracks.trackLinks, + trackOtherArtistLinks: relations.sections.tracks.trackOtherArtistLinks, + chunkDate: data.sections.tracks.chunkDates, + chunkDuration: data.sections.tracks.chunkDurations, + chunkApproximate: data.sections.tracks.chunkApproximates, + trackDurations: data.sections.tracks.trackDurations, + }).map(({ + chunkAlbumLink, + trackLinks, + trackOtherArtistLinks, + chunkDate, + chunkDuration, + chunkApproximate, + trackDurations, + }) => [ + html.tag('dt', + addAccentsToAlbumLink({ + albumLink: chunkAlbumLink, + date: chunkDate, + duration: chunkDuration, + approximate: chunkApproximate, + })), + + html.tag('dd', + html.tag('ul', + stitchArrays({ + trackLink: trackLinks, + otherArtistLinks: trackOtherArtistLinks, + duration: trackDurations, + }).map(({trackLink, duration, ...properties}) => ({ + entry: + (duration + ? language.$('artistPage.creditList.entry.track.withDuration', { + track: trackLink, + duration: language.formatDuration(duration), + }) + : language.$('artistPage.creditList.entry.track', { + track: trackLink, + })), + ...properties, + })) + .map(addAccentsToEntry) + .map(entry => html.tag('li', entry)))), + ])), + */ ], + /* sec.artworks && [ sec.artworks.heading .slots({ @@ -652,7 +574,9 @@ export default { .map(row => html.tag('li', row)))), ])), ], + */ + /* sec.commentary && [ sec.commentary.heading .slots({ @@ -681,6 +605,7 @@ export default { .map(entry => html.tag('li', entry)))), ])), ], + */ ], navLinkStyle: 'hierarchical', diff --git a/src/content/dependencies/generateArtistInfoPageChunk.js b/src/content/dependencies/generateArtistInfoPageChunk.js new file mode 100644 index 00000000..121cf43d --- /dev/null +++ b/src/content/dependencies/generateArtistInfoPageChunk.js @@ -0,0 +1,44 @@ +export default { + extraDependencies: ['html', 'language'], + + slots: { + albumLink: {type: 'html'}, + + date: {validate: v => v.isDate}, + duration: {validate: v => v.isDuration}, + durationApproximate: {type: 'boolean'}, + + items: {type: 'html'}, + }, + + generate(slots, {html, language}) { + let accentedLink = slots.albumLink; + + accent: { + const options = {album: accentedLink}; + const parts = ['artistPage.creditList.album']; + + if (slots.date) { + parts.push('withDate'); + options.date = language.formatDate(slots.date); + } + + if (slots.duration) { + parts.push('withDuration'); + options.duration = + language.formatDuration(slots.duration, { + approximate: slots.durationApproximate, + }); + } + + accentedLink = language.formatString(parts.join('.'), options); + } + + return html.tags([ + html.tag('dt', accentedLink), + html.tag('dd', + html.tag('ul', + slots.items)), + ]); + }, +}; diff --git a/src/content/dependencies/generateArtistInfoPageChunkItem.js b/src/content/dependencies/generateArtistInfoPageChunkItem.js new file mode 100644 index 00000000..9004f18a --- /dev/null +++ b/src/content/dependencies/generateArtistInfoPageChunkItem.js @@ -0,0 +1,50 @@ +export default { + extraDependencies: ['html', 'language'], + + slots: { + content: {type: 'html'}, + + otherArtistLinks: {validate: v => v.arrayOf(v.isHTML)}, + contribution: {type: 'string'}, + rerelease: {type: 'boolean'}, + }, + + generate(slots, {html, language}) { + let accentedContent = slots.content; + + accent: { + if (slots.rerelease) { + accentedContent = + language.$('artistPage.creditList.entry.rerelease', { + entry: accentedContent, + }); + + break accent; + } + + const parts = ['artistPage.creditList.entry']; + const options = {entry: accentedContent}; + + if (slots.otherArtistLinks) { + parts.push('withArtists'); + options.artists = language.formatConjunctionList(slots.otherArtistLinks); + } + + if (slots.contribution) { + parts.push('withContribution'); + options.contribution = slots.contribution; + } + + if (parts.length === 1) { + break accent; + } + + accentedContent = language.formatString(parts.join('.'), options); + } + + return ( + html.tag('li', + {class: slots.rerelease && 'rerelease'}, + accentedContent)); + }, +}; diff --git a/src/content/dependencies/generateArtistInfoPageOtherArtistLinks.js b/src/content/dependencies/generateArtistInfoPageOtherArtistLinks.js new file mode 100644 index 00000000..7667dea7 --- /dev/null +++ b/src/content/dependencies/generateArtistInfoPageOtherArtistLinks.js @@ -0,0 +1,23 @@ +import {empty} from '../../util/sugar.js'; + +export default { + contentDependencies: ['linkArtist'], + + relations(relation, contribs, artist) { + const otherArtistContribs = contribs.filter(({who}) => who !== artist); + + if (empty(otherArtistContribs)) { + return {}; + } + + const otherArtistLinks = + otherArtistContribs + .map(({who}) => relation('linkArtist', who)); + + return {otherArtistLinks}; + }, + + generate(relations) { + return relations.otherArtistLinks ?? null; + }, +}; diff --git a/src/content/dependencies/generateArtistInfoPageTracksChunkedList.js b/src/content/dependencies/generateArtistInfoPageTracksChunkedList.js new file mode 100644 index 00000000..27d8a56a --- /dev/null +++ b/src/content/dependencies/generateArtistInfoPageTracksChunkedList.js @@ -0,0 +1,187 @@ +import {accumulateSum, stitchArrays, unique} from '../../util/sugar.js'; +import {chunkByProperties, sortAlbumsTracksChronologically} from '../../util/wiki-data.js'; + +// TODO: This obviously needs to be more generalized. +function sortContributionEntries(entries, sortFunction) { + const things = unique(entries.map(({thing}) => thing)); + sortFunction(things); + + const outputArrays = []; + const thingToOutputArray = new Map(); + + for (const thing of things) { + const array = []; + thingToOutputArray.set(thing, array); + outputArrays.push(array); + } + + for (const entry of entries) { + thingToOutputArray.get(entry.thing).push(entry); + } + + entries.splice(0, entries.length, ...outputArrays.flat()); +} + +export default { + contentDependencies: [ + 'generateArtistInfoPageChunk', + 'generateArtistInfoPageChunkItem', + 'generateArtistInfoPageOtherArtistLinks', + 'linkAlbum', + 'linkTrack', + ], + + extraDependencies: ['html', 'language'], + + query(artist) { + const entries = [ + ...artist.tracksAsArtist.map(track => ({ + track, + date: track.date, + thing: track, + album: track.album, + contribs: track.artistContribs, + })), + + ...artist.tracksAsContributor.map(track => ({ + track, + date: track.date, + thing: track, + album: track.album, + contribs: track.contributorContribs, + })), + ]; + + sortContributionEntries(entries, sortAlbumsTracksChronologically); + + const chunks = chunkByProperties(entries, ['album', 'date']); + + return {entries, chunks}; + }, + + relations(relation, query, artist) { + return { + chunks: + query.chunks.map(() => relation('generateArtistInfoPageChunk')), + + albumLinks: + query.chunks.map(({album}) => relation('linkAlbum', album)), + + items: + query.chunks.map(({chunk}) => + chunk.map(() => relation('generateArtistInfoPageChunkItem'))), + + trackLinks: + query.chunks.map(({chunk}) => + chunk.map(({track}) => relation('linkTrack', track))), + + trackOtherArtistLinks: + query.chunks.map(({chunk}) => + chunk.map(({contribs}) => relation('generateArtistInfoPageOtherArtistLinks', contribs, artist))), + }; + }, + + data(query, artist) { + return { + chunkDates: + query.chunks.map(({date}) => date), + + chunkDurations: + query.chunks.map(({chunk}) => + accumulateSum( + chunk + .filter(({track}) => track.duration && track.originalReleaseTrack === null) + .map(({track}) => track.duration))), + + chunkDurationsApproximate: + query.chunks.map(({chunk}) => + chunk + .filter(({track}) => track.duration && track.originalReleaseTrack === null) + .length > 1), + + trackDurations: + query.chunks.map(({chunk}) => + chunk.map(({track}) => track.duration)), + + trackContributions: + query.chunks.map(({chunk}) => + chunk.map(({contribs}) => + contribs + .find(({who}) => who === artist) + .what)), + + trackRereleases: + query.chunks.map(({chunk}) => + chunk.map(({track}) => track.originalReleaseTrack !== null)), + }; + }, + + generate(data, relations, {html, language}) { + return html.tag('dl', + stitchArrays({ + chunk: relations.chunks, + albumLink: relations.albumLinks, + date: data.chunkDates, + duration: data.chunkDurations, + durationApproximate: data.chunkDurationsApproximate, + + items: relations.items, + trackLinks: relations.trackLinks, + trackOtherArtistLinks: relations.trackOtherArtistLinks, + trackDurations: data.trackDurations, + trackContributions: data.trackContributions, + trackRereleases: data.trackRereleases, + }).map(({ + chunk, + albumLink, + date, + duration, + durationApproximate, + + items, + trackLinks, + trackOtherArtistLinks, + trackDurations, + trackContributions, + trackRereleases, + }) => + chunk.slots({ + albumLink, + date, + duration, + durationApproximate, + + items: + stitchArrays({ + item: items, + trackLink: trackLinks, + otherArtistLinks: trackOtherArtistLinks, + duration: trackDurations, + contribution: trackContributions, + rerelease: trackRereleases, + }).map(({ + item, + trackLink, + otherArtistLinks, + duration, + contribution, + rerelease, + }) => + item.slots({ + otherArtistLinks, + contribution, + rerelease, + + content: + (duration + ? language.$('artistPage.creditList.entry.track.withDuration', { + track: trackLink, + duration: language.formatDuration(duration), + }) + : language.$('artistPage.creditList.entry.track', { + track: trackLink, + })), + })), + }))); + }, +}; |