diff options
Diffstat (limited to 'src/content')
25 files changed, 540 insertions, 566 deletions
diff --git a/src/content/dependencies/generateAlbumArtInfoBox.js b/src/content/dependencies/generateAlbumArtInfoBox.js index f0bfd1b6..8c44c930 100644 --- a/src/content/dependencies/generateAlbumArtInfoBox.js +++ b/src/content/dependencies/generateAlbumArtInfoBox.js @@ -4,12 +4,16 @@ export default { relations: (relation, album) => ({ wallpaperArtistContributionsLine: - relation('generateReleaseInfoContributionsLine', - album.wallpaperArtistContribs), + (album.wallpaperArtwork + ? relation('generateReleaseInfoContributionsLine', + album.wallpaperArtwork.artistContribs) + : null), bannerArtistContributionsLine: - relation('generateReleaseInfoContributionsLine', - album.bannerArtistContribs), + (album.bannerArtwork + ? relation('generateReleaseInfoContributionsLine', + album.bannerArtwork.artistContribs) + : null), }), generate: (relations, {html, language}) => @@ -22,12 +26,12 @@ export default { {[html.joinChildren]: html.tag('br')}, [ - relations.wallpaperArtistContributionsLine.slots({ + relations.wallpaperArtistContributionsLine?.slots({ stringKey: capsule + '.wallpaperArtBy', chronologyKind: 'wallpaperArt', }), - relations.bannerArtistContributionsLine.slots({ + relations.bannerArtistContributionsLine?.slots({ stringKey: capsule + '.bannerArtBy', chronologyKind: 'bannerArt', }), diff --git a/src/content/dependencies/generateAlbumGalleryAlbumGrid.js b/src/content/dependencies/generateAlbumGalleryAlbumGrid.js new file mode 100644 index 00000000..7f152871 --- /dev/null +++ b/src/content/dependencies/generateAlbumGalleryAlbumGrid.js @@ -0,0 +1,90 @@ +import {stitchArrays} from '#sugar'; + +export default { + contentDependencies: [ + 'generateCoverGrid', + 'image', + 'linkAlbum', + ], + + extraDependencies: ['html', 'language'], + + query: (album) => ({ + artworks: + (album.hasCoverArt + ? album.coverArtworks + : []), + }), + + relations: (relation, query, album) => ({ + coverGrid: + relation('generateCoverGrid'), + + albumLinks: + query.artworks.map(_artwork => + relation('linkAlbum', album)), + + images: + query.artworks + .map(artwork => relation('image', artwork)), + }), + + data: (query, album) => ({ + albumName: + album.name, + + artworkLabels: + query.artworks + .map(artwork => artwork.label), + + artworkArtists: + query.artworks + .map(artwork => artwork.artistContribs + .map(contrib => contrib.artist.name)), + }), + + slots: { + attributes: {type: 'attributes', mutable: false}, + }, + + generate: (data, relations, slots, {html, language}) => + html.tag('div', + {[html.onlyIfContent]: true}, + + slots.attributes, + + [ + relations.coverArtistsLine, + + relations.coverGrid.slots({ + links: + relations.albumLinks, + + names: + data.artworkLabels + .map(label => label ?? data.albumName), + + images: + stitchArrays({ + image: relations.images, + label: data.artworkLabels, + }).map(({image, label}) => + image.slots({ + missingSourceContent: + language.$('misc.albumGalleryGrid.noCoverArt', { + name: + label ?? data.albumName, + }), + })), + + info: + data.artworkArtists.map(artists => + language.$('misc.coverGrid.details.coverArtists', { + [language.onlyIfOptions]: ['artists'], + + artists: + language.formatUnitList(artists), + })), + }), + ]), +}; diff --git a/src/content/dependencies/generateAlbumGalleryPage.js b/src/content/dependencies/generateAlbumGalleryPage.js index b48d92af..2ba3b272 100644 --- a/src/content/dependencies/generateAlbumGalleryPage.js +++ b/src/content/dependencies/generateAlbumGalleryPage.js @@ -1,18 +1,18 @@ -import {compareArrays, stitchArrays} from '#sugar'; +import {stitchArrays, unique} from '#sugar'; +import {getKebabCase} from '#wiki-data'; export default { contentDependencies: [ - 'generateAlbumGalleryCoverArtistsLine', + 'generateAlbumGalleryAlbumGrid', 'generateAlbumGalleryNoTrackArtworksLine', 'generateAlbumGalleryStatsLine', + 'generateAlbumGalleryTrackGrid', 'generateAlbumNavAccent', 'generateAlbumSecondaryNav', 'generateAlbumStyleRules', - 'generateCoverGrid', + 'generateIntrapageDotSwitcher', 'generatePageLayout', - 'image', 'linkAlbum', - 'linkTrack', ], extraDependencies: ['html', 'language'], @@ -20,147 +20,82 @@ export default { query(album) { const query = {}; - const tracksWithUniqueCoverArt = + const trackArtworkLabels = album.tracks - .filter(track => track.hasUniqueCoverArt); - - // Don't display "all artwork by..." for albums where there's - // only one unique artwork in the first place. - if (tracksWithUniqueCoverArt.length > 1) { - const allCoverArtistArrays = - tracksWithUniqueCoverArt - .map(track => track.coverArtistContribs) - .map(contribs => contribs.map(contrib => contrib.artist)); - - const allSameCoverArtists = - allCoverArtistArrays - .slice(1) - .every(artists => compareArrays(artists, allCoverArtistArrays[0])); - - if (allSameCoverArtists) { - query.coverArtistsForAllTracks = - allCoverArtistArrays[0]; - } - } + .map(track => track.trackArtworks + .map(artwork => artwork.label)); + + const recurranceThreshold = 2; + + // This list may include null, if some artworks are not labelled! + // That's expected. + query.recurringTrackArtworkLabels = + unique(trackArtworkLabels.flat()) + .filter(label => + trackArtworkLabels + .filter(labels => labels.includes(label)) + .length >= + (label === null + ? 1 + : recurranceThreshold)); return query; }, - relations(relation, query, album) { - const relations = {}; + relations: (relation, query, album) => ({ + layout: + relation('generatePageLayout'), - relations.layout = - relation('generatePageLayout'); + albumStyleRules: + relation('generateAlbumStyleRules', album, null), - relations.albumStyleRules = - relation('generateAlbumStyleRules', album, null); - - relations.albumLink = - relation('linkAlbum', album); - - relations.albumNavAccent = - relation('generateAlbumNavAccent', album, null); - - relations.secondaryNav = - relation('generateAlbumSecondaryNav', album); - - relations.statsLine = - relation('generateAlbumGalleryStatsLine', album); - - if (album.tracks.every(track => !track.hasUniqueCoverArt)) { - relations.noTrackArtworksLine = - relation('generateAlbumGalleryNoTrackArtworksLine'); - } - - if (query.coverArtistsForAllTracks) { - relations.coverArtistsLine = - relation('generateAlbumGalleryCoverArtistsLine', query.coverArtistsForAllTracks); - } - - relations.coverGrid = - relation('generateCoverGrid'); - - relations.links = [ + albumLink: relation('linkAlbum', album), - ... - album.tracks - .map(track => relation('linkTrack', track)), - ]; - - relations.images = [ - (album.hasCoverArt - ? relation('image', album.artTags) - : relation('image')), + albumNavAccent: + relation('generateAlbumNavAccent', album, null), - ... - album.tracks.map(track => - (track.hasUniqueCoverArt - ? relation('image', track.artTags) - : relation('image'))), - ]; - - return relations; - }, + secondaryNav: + relation('generateAlbumSecondaryNav', album), - data(query, album) { - const data = {}; + statsLine: + relation('generateAlbumGalleryStatsLine', album), - data.name = album.name; - data.color = album.color; - - data.names = [ - album.name, - ...album.tracks.map(track => track.name), - ]; - - data.coverArtists = [ - (album.hasCoverArt - ? album.coverArtistContribs.map(({artist}) => artist.name) + noTrackArtworksLine: + (album.tracks.every(track => !track.hasUniqueCoverArt) + ? relation('generateAlbumGalleryNoTrackArtworksLine') : null), - ... - album.tracks.map(track => { - if (query.coverArtistsForAllTracks) { - return null; - } + setSwitcher: + relation('generateIntrapageDotSwitcher'), - if (track.hasUniqueCoverArt) { - return track.coverArtistContribs.map(({artist}) => artist.name); - } + albumGrid: + relation('generateAlbumGalleryAlbumGrid', album), - return null; - }), - ]; - - data.paths = [ - (album.hasCoverArt - ? ['media.albumCover', album.directory, album.coverArtFileExtension] - : null), + trackGrids: + query.recurringTrackArtworkLabels.map(label => + relation('generateAlbumGalleryTrackGrid', album, label)), + }), - ... - album.tracks.map(track => - (track.hasUniqueCoverArt - ? ['media.trackCover', track.album.directory, track.directory, track.coverArtFileExtension] - : null)), - ]; + data: (query, album) => ({ + trackGridLabels: + query.recurringTrackArtworkLabels, - data.dimensions = [ - (album.hasCoverArt - ? album.coverArtDimensions - : null), + trackGridIDs: + query.recurringTrackArtworkLabels.map(label => + 'track-grid-' + + (label + ? getKebabCase(label) + : 'no-label')), - ... - album.tracks.map(track => - (track.hasUniqueCoverArt - ? track.coverArtDimensions - : null)), - ]; + name: + album.name, - return data; - }, + color: + album.color, + }), - generate: (data, relations, {language}) => + generate: (data, relations, {html, language}) => language.encapsulate('albumGalleryPage', pageCapsule => relations.layout.slots({ title: @@ -176,34 +111,39 @@ export default { mainClasses: ['top-index'], mainContent: [ relations.statsLine, - relations.coverArtistsLine, + + relations.albumGrid, + relations.noTrackArtworksLine, - relations.coverGrid - .slots({ - links: relations.links, - names: data.names, - images: - stitchArrays({ - image: relations.images, - path: data.paths, - dimensions: data.dimensions, - name: data.names, - }).map(({image, path, dimensions, name}) => - image.slots({ - path, - dimensions, - missingSourceContent: - language.$('misc.albumGalleryGrid.noCoverArt', {name}), - })), - info: - data.coverArtists.map(names => - (names === null - ? null - : language.$('misc.coverGrid.details.coverArtists', { - artists: language.formatUnitList(names), - }))), - }), + data.trackGridLabels.some(value => value !== null) && + html.tag('p', {class: 'gallery-set-switcher'}, + language.encapsulate(pageCapsule, 'setSwitcher', switcherCapsule => + language.$(switcherCapsule, { + sets: + relations.setSwitcher.slots({ + initialOptionIndex: 0, + + titles: + data.trackGridLabels.map(label => + label ?? + language.$(switcherCapsule, 'unlabeledSet')), + + targetIDs: + data.trackGridIDs, + }), + }))), + + stitchArrays({ + grid: relations.trackGrids, + id: data.trackGridIDs, + }).map(({grid, id}, index) => + grid.slots({ + attributes: [ + {id}, + index >= 1 && {style: 'display: none'}, + ], + })), ], navLinkStyle: 'hierarchical', diff --git a/src/content/dependencies/generateAlbumGalleryTrackGrid.js b/src/content/dependencies/generateAlbumGalleryTrackGrid.js new file mode 100644 index 00000000..85e7576c --- /dev/null +++ b/src/content/dependencies/generateAlbumGalleryTrackGrid.js @@ -0,0 +1,122 @@ +import {compareArrays, stitchArrays} from '#sugar'; + +export default { + contentDependencies: [ + 'generateAlbumGalleryCoverArtistsLine', + 'generateCoverGrid', + 'image', + 'linkAlbum', + 'linkTrack', + ], + + extraDependencies: ['html', 'language'], + + query(album, label) { + const query = {}; + + query.artworks = + album.tracks.map(track => + track.trackArtworks.find(artwork => artwork.label === label) ?? + null); + + const presentArtworks = + query.artworks.filter(Boolean); + + if (presentArtworks.length > 1) { + const allArtistArrays = + presentArtworks + .map(artwork => artwork.artistContribs + .map(contrib => contrib.artist)); + + const allSameArtists = + allArtistArrays + .slice(1) + .every(artists => compareArrays(artists, allArtistArrays[0])); + + if (allSameArtists) { + query.artistsForAllTrackArtworks = + allArtistArrays[0]; + } + } + + return query; + }, + + relations: (relation, query, album, _label) => ({ + coverArtistsLine: + (query.artistsForAllTrackArtworks + ? relation('generateAlbumGalleryCoverArtistsLine', + query.artistsForAllTrackArtworks) + : null), + + coverGrid: + relation('generateCoverGrid'), + + albumLink: + relation('linkAlbum', album), + + trackLinks: + album.tracks + .map(track => relation('linkTrack', track)), + + images: + query.artworks + .map(artwork => relation('image', artwork)), + }), + + data: (query, album, _label) => ({ + trackNames: + album.tracks + .map(track => track.name), + + trackArtworkArtists: + query.artworks.map(artwork => + (query.artistsForAllTrackArtworks + ? null + : artwork + ? artwork.artistContribs + .map(contrib => contrib.artist.name) + : null)), + }), + + slots: { + attributes: {type: 'attributes', mutable: false}, + }, + + generate: (data, relations, slots, {html, language}) => + html.tag('div', + {[html.onlyIfContent]: true}, + + slots.attributes, + + [ + relations.coverArtistsLine, + + relations.coverGrid.slots({ + links: + relations.trackLinks, + + names: + data.trackNames, + + images: + stitchArrays({ + image: relations.images, + name: data.trackNames, + }).map(({image, name}) => + image.slots({ + missingSourceContent: + language.$('misc.albumGalleryGrid.noCoverArt', {name}), + })), + + info: + data.trackArtworkArtists.map(artists => + language.$('misc.coverGrid.details.coverArtists', { + [language.onlyIfOptions]: ['artists'], + + artists: + language.formatUnitList(artists), + })), + }), + ]), +}; diff --git a/src/content/dependencies/generateArtTagAncestorDescendantMapList.js b/src/content/dependencies/generateArtTagAncestorDescendantMapList.js index 89150615..80d19b5a 100644 --- a/src/content/dependencies/generateArtTagAncestorDescendantMapList.js +++ b/src/content/dependencies/generateArtTagAncestorDescendantMapList.js @@ -33,8 +33,8 @@ export default { const artTagsTimesFeaturedTotal = artTags.map(artTag => unique([ - ...artTag.directlyTaggedInThings, - ...artTag.indirectlyTaggedInThings, + ...artTag.directlyFeaturedInArtworks, + ...artTag.indirectlyFeaturedInArtworks, ]).length); const sublists = diff --git a/src/content/dependencies/generateArtTagGalleryPage.js b/src/content/dependencies/generateArtTagGalleryPage.js index d51700d4..344e7bda 100644 --- a/src/content/dependencies/generateArtTagGalleryPage.js +++ b/src/content/dependencies/generateArtTagGalleryPage.js @@ -1,5 +1,5 @@ -import {sortAlbumsTracksChronologically} from '#sort'; -import {empty, stitchArrays, unique} from '#sugar'; +import {sortArtworksChronologically} from '#sort'; +import {empty, unique} from '#sugar'; export default { contentDependencies: [ @@ -11,10 +11,9 @@ export default { 'generatePageLayout', 'generateQuickDescription', 'image', - 'linkAlbum', + 'linkAnythingMan', 'linkArtTagGallery', 'linkExternal', - 'linkTrack', ], extraDependencies: ['html', 'language', 'wikiData'], @@ -26,16 +25,13 @@ export default { }, query(sprawl, artTag) { - const directThings = artTag.directlyTaggedInThings; - const indirectThings = artTag.indirectlyTaggedInThings; - const allThings = unique([...directThings, ...indirectThings]); + const directArtworks = artTag.directlyFeaturedInArtworks; + const indirectArtworks = artTag.indirectlyFeaturedInArtworks; + const allArtworks = unique([...directArtworks, ...indirectArtworks]); - sortAlbumsTracksChronologically(allThings, { - getDate: thing => thing.coverArtDate, - latestFirst: true, - }); + sortArtworksChronologically(allArtworks, {latestFirst: true}); - return {directThings, indirectThings, allThings}; + return {directArtworks, indirectArtworks, allArtworks}; }, relations(relation, query, sprawl, artTag) { @@ -81,15 +77,12 @@ export default { relation('generateCoverGrid'); relations.links = - query.allThings - .map(thing => - (thing.album - ? relation('linkTrack', thing) - : relation('linkAlbum', thing))); + query.allArtworks + .map(artwork => relation('linkAnythingMan', artwork.thing)); relations.images = - query.allThings - .map(thing => relation('image', thing.artTags)); + query.allArtworks + .map(artwork => relation('image', artwork)); return relations; }, @@ -102,30 +95,22 @@ export default { data.name = artTag.name; data.color = artTag.color; - data.numArtworksIndirectly = query.indirectThings.length; - data.numArtworksDirectly = query.directThings.length; - data.numArtworksTotal = query.allThings.length; + data.numArtworksIndirectly = query.indirectArtworks.length; + data.numArtworksDirectly = query.directArtworks.length; + data.numArtworksTotal = query.allArtworks.length; data.names = - query.allThings.map(thing => thing.name); - - data.paths = - query.allThings.map(thing => - (thing.album - ? ['media.trackCover', thing.album.directory, thing.directory, thing.coverArtFileExtension] - : ['media.albumCover', thing.directory, thing.coverArtFileExtension])); - - data.dimensions = - query.allThings.map(thing => thing.coverArtDimensions); + query.allArtworks + .map(artwork => artwork.thing.name); data.coverArtists = - query.allThings.map(thing => - thing.coverArtistContribs - .map(({artist}) => artist.name)); + query.allArtworks + .map(artwork => artwork.artistContribs + .map(contrib => contrib.artist.name)); data.onlyFeaturedIndirectly = - query.allThings.map(thing => - !query.directThings.includes(thing)); + query.allArtworks.map(artwork => + !query.directArtworks.includes(artwork)); data.hasMixedDirectIndirect = data.onlyFeaturedIndirectly.includes(true) && @@ -210,6 +195,7 @@ export default { relations.coverGrid .slots({ links: relations.links, + images: relations.images, names: data.names, lazy: 12, @@ -217,17 +203,6 @@ export default { data.onlyFeaturedIndirectly.map(onlyFeaturedIndirectly => (onlyFeaturedIndirectly ? 'featured-indirectly' : '')), - images: - stitchArrays({ - image: relations.images, - path: data.paths, - dimensions: data.dimensions, - }).map(({image, path, dimensions}) => - image.slots({ - path, - dimensions, - })), - info: data.coverArtists.map(names => (names === null diff --git a/src/content/dependencies/generateArtTagInfoPage.js b/src/content/dependencies/generateArtTagInfoPage.js index 7765f159..9df51b77 100644 --- a/src/content/dependencies/generateArtTagInfoPage.js +++ b/src/content/dependencies/generateArtTagInfoPage.js @@ -23,10 +23,10 @@ export default { const query = {}; query.directThings = - artTag.directlyTaggedInThings; + artTag.directlyFeaturedInArtworks; query.indirectThings = - artTag.indirectlyTaggedInThings; + artTag.indirectlyFeaturedInArtworks; query.allThings = unique([...query.directThings, ...query.indirectThings]); @@ -111,8 +111,8 @@ export default { directDescendantTimesFeaturedTotal: artTag.directDescendantArtTags.map(artTag => unique([ - ...artTag.directlyTaggedInThings, - ...artTag.indirectlyTaggedInThings, + ...artTag.directlyFeaturedInArtworks, + ...artTag.indirectlyFeaturedInArtworks, ]).length), }), diff --git a/src/content/dependencies/generateArtTagSidebar.js b/src/content/dependencies/generateArtTagSidebar.js index c281b93d..9e2f813c 100644 --- a/src/content/dependencies/generateArtTagSidebar.js +++ b/src/content/dependencies/generateArtTagSidebar.js @@ -54,8 +54,8 @@ export default { directDescendantTimesFeaturedTotal: artTag.directDescendantArtTags.map(artTag => unique([ - ...artTag.directlyTaggedInThings, - ...artTag.indirectlyTaggedInThings, + ...artTag.directlyFeaturedInArtworks, + ...artTag.indirectlyFeaturedInArtworks, ]).length), furthestAncestorArtTagNames: diff --git a/src/content/dependencies/generateArtistArtworkColumn.js b/src/content/dependencies/generateArtistArtworkColumn.js new file mode 100644 index 00000000..a4135489 --- /dev/null +++ b/src/content/dependencies/generateArtistArtworkColumn.js @@ -0,0 +1,13 @@ +export default { + contentDependencies: ['generateCoverArtwork'], + + relations: (relation, artist) => ({ + coverArtwork: + (artist.hasAvatar + ? relation('generateCoverArtwork', artist.avatarArtwork) + : null), + }), + + generate: (relations) => + relations.coverArtwork, +}; diff --git a/src/content/dependencies/generateArtistGalleryPage.js b/src/content/dependencies/generateArtistGalleryPage.js index 38696c9c..6a24275e 100644 --- a/src/content/dependencies/generateArtistGalleryPage.js +++ b/src/content/dependencies/generateArtistGalleryPage.js @@ -1,5 +1,4 @@ -import {sortAlbumsTracksChronologically} from '#sort'; -import {stitchArrays} from '#sugar'; +import {sortArtworksChronologically} from '#sort'; export default { contentDependencies: [ @@ -7,83 +6,59 @@ export default { 'generateCoverGrid', 'generatePageLayout', 'image', - 'linkAlbum', - 'linkTrack', + 'linkAnythingMan', ], extraDependencies: ['html', 'language'], - query(artist) { - const things = - ([ - artist.albumCoverArtistContributions, - artist.trackCoverArtistContributions, - ]).flat() - .filter(({annotation}) => !annotation?.startsWith(`edits for wiki`)) - .map(({thing}) => thing); - - sortAlbumsTracksChronologically(things, { - latestFirst: true, - getDate: thing => thing.coverArtDate, - }); - - return {things}; - }, - - relations(relation, query, artist) { - const relations = {}; - - relations.layout = - relation('generatePageLayout'); - - relations.artistNavLinks = - relation('generateArtistNavLinks', artist); - - relations.coverGrid = - relation('generateCoverGrid'); - - relations.links = - query.things.map(thing => - (thing.album - ? relation('linkTrack', thing) - : relation('linkAlbum', thing))); - - relations.images = - query.things.map(thing => - relation('image', thing.artTags)); - - return relations; - }, - - data(query, artist) { - const data = {}; - - data.name = artist.name; - - data.numArtworks = query.things.length; - - data.names = - query.things.map(thing => thing.name); - - data.paths = - query.things.map(thing => - (thing.album - ? ['media.trackCover', thing.album.directory, thing.directory, thing.coverArtFileExtension] - : ['media.albumCover', thing.directory, thing.coverArtFileExtension])); - - data.dimensions = - query.things.map(thing => thing.coverArtDimensions); - - data.otherCoverArtists = - query.things.map(thing => - (thing.coverArtistContribs.length > 1 - ? thing.coverArtistContribs - .filter(({artist: otherArtist}) => otherArtist !== artist) - .map(({artist: otherArtist}) => otherArtist.name) - : null)); - - return data; - }, + query: (artist) => ({ + artworks: + sortArtworksChronologically( + ([ + artist.albumCoverArtistContributions, + artist.trackCoverArtistContributions, + ]).flat() + .filter(contrib => !contrib.annotation?.startsWith(`edits for wiki`)) + .map(contrib => contrib.thing), + {latestFirst: true}), + }), + + relations: (relation, query, artist) => ({ + layout: + relation('generatePageLayout'), + + artistNavLinks: + relation('generateArtistNavLinks', artist), + + coverGrid: + relation('generateCoverGrid'), + + links: + query.artworks + .map(artwork => relation('linkAnythingMan', artwork.thing)), + + images: + query.artworks + .map(artwork => relation('image', artwork)), + }), + + data: (query, artist) => ({ + name: + artist.name, + + numArtworks: + query.artworks.length, + + names: + query.artworks + .map(artwork => artwork.thing.name), + + otherCoverArtists: + query.artworks + .map(artwork => artwork.artistContribs + .filter(contrib => contrib.artist !== artist) + .map(contrib => contrib.artist.name)), + }), generate: (data, relations, {html, language}) => language.encapsulate('artistGalleryPage', pageCapsule => @@ -100,7 +75,7 @@ export default { html.tag('p', {class: 'quick-info'}, language.$(pageCapsule, 'infoLine', { coverArts: - language.countCoverArts(data.numArtworks, { + language.countArtworks(data.numArtworks, { unit: true, }), })), @@ -108,27 +83,16 @@ export default { relations.coverGrid .slots({ links: relations.links, + images: relations.images, names: data.names, - images: - stitchArrays({ - image: relations.images, - path: data.paths, - dimensions: data.dimensions, - }).map(({image, path, dimensions}) => - image.slots({ - path, - dimensions, - })), - - // TODO: Can this be [language.onlyIfOptions]? info: data.otherCoverArtists.map(names => - (names === null - ? null - : language.$('misc.coverGrid.details.otherCoverArtists', { - artists: language.formatUnitList(names), - }))), + language.$('misc.coverGrid.details.otherCoverArtists', { + [language.onlyIfOptions]: ['artists'], + + artists: language.formatUnitList(names), + })), }), ], diff --git a/src/content/dependencies/generateArtistInfoPage.js b/src/content/dependencies/generateArtistInfoPage.js index bd5e537a..3a3cf8b7 100644 --- a/src/content/dependencies/generateArtistInfoPage.js +++ b/src/content/dependencies/generateArtistInfoPage.js @@ -2,6 +2,7 @@ import {empty, stitchArrays, unique} from '#sugar'; export default { contentDependencies: [ + 'generateArtistArtworkColumn', 'generateArtistGroupContributionsInfo', 'generateArtistInfoPageArtworksChunkedList', 'generateArtistInfoPageCommentaryChunkedList', @@ -9,9 +10,7 @@ export default { 'generateArtistInfoPageTracksChunkedList', 'generateArtistNavLinks', 'generateContentHeading', - 'generateCoverArtwork', 'generatePageLayout', - 'image', 'linkArtistGallery', 'linkExternal', 'linkGroup', @@ -69,15 +68,8 @@ export default { artistNavLinks: relation('generateArtistNavLinks', artist), - cover: - (artist.hasAvatar - ? relation('generateCoverArtwork', [], []) - : null), - - image: - (artist.hasAvatar - ? relation('image') - : null), + artworkColumn: + relation('generateArtistArtworkColumn', artist), contentHeading: relation('generateContentHeading'), @@ -131,14 +123,6 @@ export default { name: artist.name, - directory: - artist.directory, - - avatarFileExtension: - (artist.hasAvatar - ? artist.avatarFileExtension - : null), - closeGroupAnnotations: query.generalLinkedGroups .map(({annotation}) => annotation), @@ -156,19 +140,8 @@ export default { title: data.name, headingMode: 'sticky', - coverColumnContent: - (relations.cover - ? relations.cover.slots({ - image: - relations.image.slots({ - path: [ - 'media.artistAvatar', - data.directory, - data.avatarFileExtension, - ], - }), - }) - : null), + artworkColumnContent: + relations.artworkColumn, mainContent: [ html.tags([ diff --git a/src/content/dependencies/generateCoverArtwork.js b/src/content/dependencies/generateCoverArtwork.js index 71c0747d..3a10ab20 100644 --- a/src/content/dependencies/generateCoverArtwork.js +++ b/src/content/dependencies/generateCoverArtwork.js @@ -11,7 +11,7 @@ export default { relations: (relation, artwork) => ({ image: - relation('image'), + relation('image', artwork), originDetails: relation('generateCoverArtworkOriginDetails', artwork), @@ -28,18 +28,10 @@ export default { data: (artwork) => ({ color: - artwork.thing.color, - - path: - artwork.path, + artwork.thing.color ?? null, dimensions: artwork.dimensions, - - warnings: - artwork.artTags - .filter(tag => tag.isContentWarning) - .map(tag => tag.name), }), slots: { @@ -69,9 +61,6 @@ export default { const {image} = relations; image.setSlots({ - path: data.path, - warnings: data.warnings, - color: slots.color ?? data.color, alt: slots.alt, }); diff --git a/src/content/dependencies/generateCoverGrid.js b/src/content/dependencies/generateCoverGrid.js index 1898832f..29ac08b7 100644 --- a/src/content/dependencies/generateCoverGrid.js +++ b/src/content/dependencies/generateCoverGrid.js @@ -33,9 +33,11 @@ export default { actionLinks: {validate: v => v.sparseArrayOf(v.isHTML)}, }, - generate(relations, slots, {html, language}) { - return ( - html.tag('div', {class: 'grid-listing'}, [ + generate: (relations, slots, {html, language}) => + html.tag('div', {class: 'grid-listing'}, + {[html.onlyIfContent]: true}, + + [ stitchArrays({ classes: slots.classes, image: slots.images, @@ -84,6 +86,5 @@ export default { relations.actionLinks .slot('actionLinks', slots.actionLinks), - ])); - }, + ]), }; diff --git a/src/content/dependencies/generateFlashActGalleryPage.js b/src/content/dependencies/generateFlashActGalleryPage.js index 8f174b21..84ab549d 100644 --- a/src/content/dependencies/generateFlashActGalleryPage.js +++ b/src/content/dependencies/generateFlashActGalleryPage.js @@ -1,5 +1,3 @@ -import {stitchArrays} from '#sugar'; - import striptags from 'striptags'; export default { @@ -37,7 +35,7 @@ export default { coverGridImages: act.flashes - .map(_flash => relation('image')), + .map(flash => relation('image', flash.coverArtwork)), flashLinks: act.flashes @@ -50,10 +48,6 @@ export default { flashNames: act.flashes.map(flash => flash.name), - - flashCoverPaths: - act.flashes.map(flash => - ['media.flashArt', flash.directory, flash.coverArtFileExtension]) }), generate: (data, relations, {language}) => @@ -71,15 +65,9 @@ export default { mainContent: [ relations.coverGrid.slots({ links: relations.flashLinks, + images: relations.coverGridImages, names: data.flashNames, lazy: 6, - - images: - stitchArrays({ - image: relations.coverGridImages, - path: data.flashCoverPaths, - }).map(({image, path}) => - image.slot('path', path)), }), ], diff --git a/src/content/dependencies/generateFlashIndexPage.js b/src/content/dependencies/generateFlashIndexPage.js index a21bb49e..2788406c 100644 --- a/src/content/dependencies/generateFlashIndexPage.js +++ b/src/content/dependencies/generateFlashIndexPage.js @@ -53,7 +53,7 @@ export default { actCoverGridImages: query.flashActs .map(act => act.flashes - .map(() => relation('image'))), + .map(flash => relation('image', flash.coverArtwork))), }), data: (query) => ({ @@ -73,11 +73,6 @@ export default { query.flashActs .map(act => act.flashes .map(flash => flash.name)), - - actCoverGridPaths: - query.flashActs - .map(act => act.flashes - .map(flash => ['media.flashArt', flash.directory, flash.coverArtFileExtension])), }), generate: (data, relations, {html, language}) => @@ -116,7 +111,6 @@ export default { coverGridImages: relations.actCoverGridImages, coverGridLinks: relations.actCoverGridLinks, coverGridNames: data.actCoverGridNames, - coverGridPaths: data.actCoverGridPaths, }).map(({ colorStyle, actLink, @@ -126,7 +120,6 @@ export default { coverGridImages, coverGridLinks, coverGridNames, - coverGridPaths, }, index) => [ html.tag('h2', {id: anchor}, @@ -135,15 +128,9 @@ export default { coverGrid.slots({ links: coverGridLinks, + images: coverGridImages, names: coverGridNames, lazy: index === 0 ? 4 : true, - - images: - stitchArrays({ - image: coverGridImages, - path: coverGridPaths, - }).map(({image, path}) => - image.slot('path', path)), }), ]), ], diff --git a/src/content/dependencies/generateGroupGalleryPage.js b/src/content/dependencies/generateGroupGalleryPage.js index 206c495d..d51366ca 100644 --- a/src/content/dependencies/generateGroupGalleryPage.js +++ b/src/content/dependencies/generateGroupGalleryPage.js @@ -53,7 +53,7 @@ export default { relations.carouselImages = carouselAlbums - .map(album => relation('image', album.artTags)); + .map(album => relation('image', album.coverArtworks[0])); } relations.quickDescription = @@ -69,7 +69,7 @@ export default { relations.gridImages = albums.map(album => (album.hasCoverArt - ? relation('image', album.artTags) + ? relation('image', album.coverArtworks[0]) : relation('image'))); return relations; @@ -92,22 +92,6 @@ export default { data.gridDurations = albums.map(album => getTotalDuration(album.tracks)); data.gridNumTracks = albums.map(album => album.tracks.length); - data.gridPaths = - albums.map(album => - (album.hasCoverArt - ? ['media.albumCover', album.directory, album.coverArtFileExtension] - : null)); - - const carouselAlbums = filterItemsForCarousel(group.featuredAlbums); - - if (!empty(group.featuredAlbums)) { - data.carouselPaths = - carouselAlbums.map(album => - (album.hasCoverArt - ? ['media.albumCover', album.directory, album.coverArtFileExtension] - : null)); - } - return data; }, @@ -124,12 +108,7 @@ export default { relations.coverCarousel ?.slots({ links: relations.carouselLinks, - images: - stitchArrays({ - image: relations.carouselImages, - path: data.carouselPaths, - }).map(({image, path}) => - image.slot('path', path)), + images: relations.carouselImages, }), relations.quickDescription, @@ -159,19 +138,19 @@ export default { .slots({ links: relations.gridLinks, names: data.gridNames, + images: stitchArrays({ image: relations.gridImages, - path: data.gridPaths, name: data.gridNames, - }).map(({image, path, name}) => + }).map(({image, name}) => image.slots({ - path, missingSourceContent: language.$('misc.coverGrid.noCoverArt', { album: name, }), })), + info: stitchArrays({ numTracks: data.gridNumTracks, diff --git a/src/content/dependencies/generateReferencedArtworksPage.js b/src/content/dependencies/generateReferencedArtworksPage.js index 5733631d..154b4762 100644 --- a/src/content/dependencies/generateReferencedArtworksPage.js +++ b/src/content/dependencies/generateReferencedArtworksPage.js @@ -1,5 +1,3 @@ -import {stitchArrays} from '#sugar'; - export default { contentDependencies: [ 'generateCoverArtwork', @@ -27,7 +25,7 @@ export default { images: artwork.referencedArtworks.map(({artwork}) => - relation('image', artwork.artTags)), + relation('image', artwork)), }), data: (artwork) => ({ @@ -41,14 +39,6 @@ export default { artwork.referencedArtworks .map(({artwork}) => artwork.thing.name), - paths: - artwork.referencedArtworks - .map(({artwork}) => artwork.path), - - dimensions: - artwork.referencedArtworks - .map(({artwork}) => artwork.dimensions), - coverArtistNames: artwork.referencedArtworks .map(({artwork}) => @@ -91,19 +81,9 @@ export default { relations.coverGrid.slots({ links: relations.links, + images: relations.images, names: data.names, - images: - stitchArrays({ - image: relations.images, - path: data.paths, - dimensions: data.dimensions, - }).map(({image, path, dimensions}) => - image.slots({ - path, - dimensions, - })), - info: data.coverArtistNames.map(names => language.$('misc.coverGrid.details.coverArtists', { diff --git a/src/content/dependencies/generateReferencingArtworksPage.js b/src/content/dependencies/generateReferencingArtworksPage.js index 520a33c3..55977b37 100644 --- a/src/content/dependencies/generateReferencingArtworksPage.js +++ b/src/content/dependencies/generateReferencingArtworksPage.js @@ -1,5 +1,3 @@ -import {stitchArrays} from '#sugar'; - export default { contentDependencies: [ 'generateCoverArtwork', @@ -27,7 +25,7 @@ export default { images: artwork.referencedByArtworks.map(({artwork}) => - relation('image', artwork.artTags)), + relation('image', artwork)), }), data: (artwork) => ({ @@ -41,14 +39,6 @@ export default { artwork.referencedByArtworks .map(({artwork}) => artwork.thing.name), - paths: - artwork.referencedByArtworks - .map(({artwork}) => artwork.path), - - dimensions: - artwork.referencedByArtworks - .map(({artwork}) => artwork.dimensions), - coverArtistNames: artwork.referencedByArtworks .map(({artwork}) => @@ -91,19 +81,9 @@ export default { relations.coverGrid.slots({ links: relations.links, + images: relations.images, names: data.names, - images: - stitchArrays({ - image: relations.images, - path: data.paths, - dimensions: data.dimensions, - }).map(({image, path, dimensions}) => - image.slots({ - path, - dimensions, - })), - info: data.coverArtistNames.map(names => language.$('misc.coverGrid.details.coverArtists', { diff --git a/src/content/dependencies/generateWikiHomepageAlbumCarouselRow.js b/src/content/dependencies/generateWikiHomepageAlbumCarouselRow.js index 3068d951..b45bfc19 100644 --- a/src/content/dependencies/generateWikiHomepageAlbumCarouselRow.js +++ b/src/content/dependencies/generateWikiHomepageAlbumCarouselRow.js @@ -1,5 +1,3 @@ -import {stitchArrays} from '#sugar'; - export default { contentDependencies: ['generateCoverCarousel', 'image', 'linkAlbum'], @@ -13,27 +11,12 @@ export default { images: row.albums - .map(album => relation('image', album.artTags)), - }), - - data: (row) => ({ - paths: - row.albums.map(album => - (album.hasCoverArt - ? ['media.albumCover', album.directory, album.coverArtFileExtension] - : null)), + .map(album => relation('image', album.coverArtworks[0])), }), - generate: (data, relations) => + generate: (relations) => relations.coverCarousel.slots({ - links: - relations.links, - - images: - stitchArrays({ - image: relations.images, - path: data.paths, - }).map(({image, path}) => - image.slot('path', path)), + links: relations.links, + images: relations.images, }), }; diff --git a/src/content/dependencies/generateWikiHomepageAlbumGridRow.js b/src/content/dependencies/generateWikiHomepageAlbumGridRow.js index c1d2c79d..a00136ba 100644 --- a/src/content/dependencies/generateWikiHomepageAlbumGridRow.js +++ b/src/content/dependencies/generateWikiHomepageAlbumGridRow.js @@ -45,20 +45,17 @@ export default { images: sprawl.albums - .map(album => relation('image', album.artTags)), + .map(album => + relation('image', + (album.hasCoverArt + ? album.coverArtworks[0] + : null))), }), data: (sprawl, _row) => ({ names: sprawl.albums .map(album => album.name), - - paths: - sprawl.albums - .map(album => - (album.hasCoverArt - ? ['media.albumCover', album.directory, album.coverArtFileExtension] - : null)), }), generate: (data, relations, {language}) => @@ -69,11 +66,9 @@ export default { images: stitchArrays({ image: relations.images, - path: data.paths, name: data.names, - }).map(({image, path, name}) => + }).map(({image, name}) => image.slots({ - path, missingSourceContent: language.$('misc.coverGrid.noCoverArt', { album: name, diff --git a/src/content/dependencies/image.js b/src/content/dependencies/image.js index bc268ec1..bf47b14f 100644 --- a/src/content/dependencies/image.js +++ b/src/content/dependencies/image.js @@ -16,68 +16,77 @@ export default { contentDependencies: ['generateColorStyleAttribute'], - relations: (relation) => ({ + relations: (relation, _artwork) => ({ colorStyle: relation('generateColorStyleAttribute'), }), - data(artTags) { - const data = {}; - - if (artTags) { - data.contentWarnings = - artTags - .filter(artTag => artTag.isContentWarning) - .map(artTag => artTag.name); - } else { - data.contentWarnings = null; - } - - return data; - }, + data: (artwork) => ({ + path: + (artwork + ? artwork.path + : null), + + warnings: + (artwork + ? artwork.artTags + .filter(artTag => artTag.isContentWarning) + .map(artTag => artTag.name) + : null), + + dimensions: + (artwork + ? artwork.dimensions + : null), + }), slots: { - src: {type: 'string'}, - - path: { - validate: v => v.validateArrayItems(v.isString), - }, - thumb: {type: 'string'}, + reveal: {type: 'boolean', default: true}, + lazy: {type: 'boolean', default: false}, + square: {type: 'boolean', default: false}, + link: { validate: v => v.anyOf(v.isBoolean, v.isString), default: false, }, - color: { - validate: v => v.isColor, - }, + color: {validate: v => v.isColor}, - warnings: { - validate: v => v.looseArrayOf(v.isString), + // Added to the .image-container. + attributes: { + type: 'attributes', + mutable: false, }, - reveal: {type: 'boolean', default: true}, - lazy: {type: 'boolean', default: false}, - - square: {type: 'boolean', default: false}, + // Added to the <img> itself. + alt: {type: 'string'}, - dimensions: { - validate: v => v.isDimensions, - }, + // Specify 'src' or 'path', or the path will be used from the artwork. + // If none of the above is present, the message in missingSourceContent + // will be displayed instead. - alt: {type: 'string'}, + src: {type: 'string'}, - attributes: { - type: 'attributes', - mutable: false, + path: { + validate: v => v.validateArrayItems(v.isString), }, missingSourceContent: { type: 'html', mutable: false, }, + + // These will also be used from the artwork if not specified as slots. + + warnings: { + validate: v => v.looseArrayOf(v.isString), + }, + + dimensions: { + validate: v => v.isDimensions, + }, }, generate(data, relations, slots, { @@ -91,15 +100,14 @@ export default { missingImagePaths, to, }) { - let originalSrc; - - if (slots.src) { - originalSrc = slots.src; - } else if (!empty(slots.path)) { - originalSrc = to(...slots.path); - } else { - originalSrc = ''; - } + const originalSrc = + (slots.src + ? slots.src + : slots.path + ? to(...slots.path) + : data.path + ? to(...data.path) + : ''); // TODO: This feels janky. It's necessary to deal with static content that // includes strings like <img src="media/misc/foo.png">, but processing the @@ -121,29 +129,27 @@ export default { !isMissingImageFile && (typeof slots.link === 'string' || slots.link); - const contentWarnings = - slots.warnings ?? - data.contentWarnings; + const warnings = slots.warnings ?? data.warnings; + const dimensions = slots.dimensions ?? data.dimensions; const willReveal = slots.reveal && originalSrc && !isMissingImageFile && - !empty(contentWarnings); - - const willSquare = - slots.square; + !empty(warnings); const imgAttributes = html.attributes([ {class: 'image'}, slots.alt && {alt: slots.alt}, - slots.dimensions?.[0] && - {width: slots.dimensions[0]}, + dimensions && + dimensions[0] && + {width: dimensions[0]}, - slots.dimensions?.[1] && - {height: slots.dimensions[1]}, + dimensions && + dimensions[1] && + {height: dimensions[1]}, ]); const isPlaceholder = @@ -169,7 +175,7 @@ export default { html.tag('span', {class: 'reveal-warnings'}, language.$('misc.contentWarnings.warnings', { - warnings: language.formatUnitList(contentWarnings), + warnings: language.formatUnitList(warnings), })), html.tag('br'), @@ -323,14 +329,14 @@ export default { wrapped = html.tag('div', {class: 'image-outer-area'}, - willSquare && + slots.square && {class: 'square-content'}, wrapped); wrapped = html.tag('div', {class: 'image-container'}, - willSquare && + slots.square && {class: 'square'}, typeof slots.link === 'string' && diff --git a/src/content/dependencies/listArtTagNetwork.js b/src/content/dependencies/listArtTagNetwork.js index 5386dcdc..93dd4ce8 100644 --- a/src/content/dependencies/listArtTagNetwork.js +++ b/src/content/dependencies/listArtTagNetwork.js @@ -29,21 +29,21 @@ export default { const getStats = (artTag) => ({ directUses: - artTag.directlyTaggedInThings.length, + artTag.directlyFeaturedInArtworks.length, // Not currently displayed directAndIndirectUses: unique([ - ...artTag.indirectlyTaggedInThings, - ...artTag.directlyTaggedInThings, + ...artTag.indirectlyFeaturedInArtworks, + ...artTag.directlyFeaturedInArtworks, ]).length, totalUses: [ - ...artTag.directlyTaggedInThings, + ...artTag.directlyFeaturedInArtworks, ... artTag.allDescendantArtTags - .flatMap(artTag => artTag.directlyTaggedInThings), + .flatMap(artTag => artTag.directlyFeaturedInArtworks), ].length, descendants: diff --git a/src/content/dependencies/listArtTagsByName.js b/src/content/dependencies/listArtTagsByName.js index 31856478..1df9dfff 100644 --- a/src/content/dependencies/listArtTagsByName.js +++ b/src/content/dependencies/listArtTagsByName.js @@ -35,8 +35,8 @@ export default { counts: query.artTags.map(artTag => unique([ - ...artTag.indirectlyTaggedInThings, - ...artTag.directlyTaggedInThings, + ...artTag.indirectlyFeaturedInArtworks, + ...artTag.directlyFeaturedInArtworks, ]).length), }; }, diff --git a/src/content/dependencies/listArtTagsByUses.js b/src/content/dependencies/listArtTagsByUses.js index fcd324f7..eca7f1c6 100644 --- a/src/content/dependencies/listArtTagsByUses.js +++ b/src/content/dependencies/listArtTagsByUses.js @@ -17,8 +17,8 @@ export default { const counts = artTags.map(artTag => unique([ - ...artTag.directlyTaggedInThings, - ...artTag.indirectlyTaggedInThings, + ...artTag.directlyFeaturedInArtworks, + ...artTag.indirectlyFeaturedInArtworks, ]).length); filterByCount(artTags, counts); diff --git a/src/content/dependencies/listArtistsByGroup.js b/src/content/dependencies/listArtistsByGroup.js index 0bf9dd2d..17096cfc 100644 --- a/src/content/dependencies/listArtistsByGroup.js +++ b/src/content/dependencies/listArtistsByGroup.js @@ -37,20 +37,25 @@ export default { ([ (unique( ([ - artist.albumArtistContributions, - artist.albumCoverArtistContributions, - artist.albumWallpaperArtistContributions, - artist.albumBannerArtistContributions, + artist.albumArtistContributions + .map(contrib => contrib.thing), + artist.albumCoverArtistContributions + .map(contrib => contrib.thing.thing), + artist.albumWallpaperArtistContributions + .map(contrib => contrib.thing.thing), + artist.albumBannerArtistContributions + .map(contrib => contrib.thing.thing), ]).flat() - .map(({thing}) => thing) )).map(album => album.groups), (unique( ([ - artist.trackArtistContributions, - artist.trackContributorContributions, - artist.trackCoverArtistContributions, + artist.trackArtistContributions + .map(contrib => contrib.thing), + artist.trackContributorContributions + .map(contrib => contrib.thing), + artist.trackCoverArtistContributions + .map(contrib => contrib.thing.thing), ]).flat() - .map(({thing}) => thing) )).map(track => track.album.groups), ]).flat() .map(groups => groups |