diff options
-rw-r--r-- | src/content/dependencies/generateArtistInfoPage.js | 9 | ||||
-rw-r--r-- | src/content/dependencies/generateCoverArtwork.js | 2 | ||||
-rw-r--r-- | src/content/dependencies/generatePageLayout.js | 2 | ||||
-rw-r--r-- | src/content/dependencies/generateStickyHeadingContainer.js | 8 | ||||
-rw-r--r-- | src/content/dependencies/generateTrackInfoPage.js | 1 | ||||
-rw-r--r-- | src/content/dependencies/generateTrackInfoPageContent.js | 19 | ||||
-rw-r--r-- | src/content/dependencies/image.js | 8 | ||||
-rw-r--r-- | src/data/things/thing.js | 26 | ||||
-rw-r--r-- | src/data/things/track.js | 2 | ||||
-rw-r--r-- | src/data/yaml.js | 2 | ||||
-rw-r--r-- | src/listing-spec.js | 3 | ||||
-rw-r--r-- | src/page/artist.js | 13 | ||||
-rw-r--r-- | src/static/site4.css | 4 | ||||
-rwxr-xr-x | src/upd8.js | 2 | ||||
-rw-r--r-- | src/util/wiki-data.js | 105 |
15 files changed, 143 insertions, 63 deletions
diff --git a/src/content/dependencies/generateArtistInfoPage.js b/src/content/dependencies/generateArtistInfoPage.js index 821512b8..a91eebf2 100644 --- a/src/content/dependencies/generateArtistInfoPage.js +++ b/src/content/dependencies/generateArtistInfoPage.js @@ -585,7 +585,7 @@ export function write(artist, {wikiData}) { let flashes, flashListChunks; if (wikiInfo.enableFlashesAndGames) { - flashes = sortChronologically(artist.flashesAsContributor.slice()); + flashes = sortFlashesChronologically(artist.flashesAsContributor.slice()); flashListChunks = chunkByProperties( flashes.map((flash) => ({ act: flash.act, @@ -760,6 +760,13 @@ export function write(artist, {wikiData}) { }, }; + const artThingsGallery = sortAlbumsTracksChronologically( + [ + ...(artist.albumsAsCoverArtist ?? []), + ...(artist.tracksAsCoverArtist ?? []), + ], + {latestFirst: true, getDate: (o) => o.coverArtDate}); + const galleryPage = hasGallery && { type: 'page', path: ['artistGallery', artist.directory], diff --git a/src/content/dependencies/generateCoverArtwork.js b/src/content/dependencies/generateCoverArtwork.js index 68680060..a7a7f859 100644 --- a/src/content/dependencies/generateCoverArtwork.js +++ b/src/content/dependencies/generateCoverArtwork.js @@ -51,6 +51,7 @@ export default { alt: slots.alt, thumb: 'medium', id: 'cover-art', + reveal: true, link: true, square: true, }), @@ -68,6 +69,7 @@ export default { path: slots.path, alt: slots.alt, thumb: 'small', + reveal: false, link: false, square: true, }); diff --git a/src/content/dependencies/generatePageLayout.js b/src/content/dependencies/generatePageLayout.js index 32effbfe..55f5b940 100644 --- a/src/content/dependencies/generatePageLayout.js +++ b/src/content/dependencies/generatePageLayout.js @@ -102,6 +102,7 @@ export default { slots: { title: {type: 'html'}, cover: {type: 'html'}, + coverNeedsReveal: {type: 'boolean'}, socialEmbed: {type: 'html'}, @@ -201,6 +202,7 @@ export default { relations.stickyHeadingContainer.slots({ title: slots.title, cover: slots.cover, + needsReveal: slots.coverNeedsReveal, }); break; case 'static': diff --git a/src/content/dependencies/generateStickyHeadingContainer.js b/src/content/dependencies/generateStickyHeadingContainer.js index c08ca08d..fb6d8307 100644 --- a/src/content/dependencies/generateStickyHeadingContainer.js +++ b/src/content/dependencies/generateStickyHeadingContainer.js @@ -8,6 +8,7 @@ export default { slots: { title: {type: 'html'}, cover: {type: 'html'}, + needsReveal: {type: 'boolean', default: false}, }, content(slots) { @@ -26,7 +27,12 @@ export default { hasCover && html.tag('div', {class: 'content-sticky-heading-cover-container'}, - html.tag('div', {class: 'content-sticky-heading-cover'}, + html.tag('div', + {class: [ + 'content-sticky-heading-cover', + slots.needsReveal && + 'content-sticky-heading-cover-needs-reveal', + ]}, slots.cover.slot('displayMode', 'thumbnail'))) ]), diff --git a/src/content/dependencies/generateTrackInfoPage.js b/src/content/dependencies/generateTrackInfoPage.js index 4795bac6..ee68f534 100644 --- a/src/content/dependencies/generateTrackInfoPage.js +++ b/src/content/dependencies/generateTrackInfoPage.js @@ -84,6 +84,7 @@ export default { additionalStyleRules: [relations.albumStyleRules], cover: relations.content.cover, + coverNeedsReveal: relations.content.coverNeedsReveal, mainContent: relations.content.main.content, navLinkStyle: 'hierarchical', diff --git a/src/content/dependencies/generateTrackInfoPageContent.js b/src/content/dependencies/generateTrackInfoPageContent.js index 67975cb4..c33c2f62 100644 --- a/src/content/dependencies/generateTrackInfoPageContent.js +++ b/src/content/dependencies/generateTrackInfoPageContent.js @@ -1,5 +1,5 @@ import {empty} from '../../util/sugar.js'; -import {sortChronologically} from '../../util/wiki-data.js'; +import {sortFlashesChronologically} from '../../util/wiki-data.js'; export default { contentDependencies: [ @@ -12,6 +12,7 @@ export default { 'linkAlbum', 'linkContribution', 'linkExternal', + 'linkFlash', 'linkTrack', 'transformContent', ], @@ -32,8 +33,10 @@ export default { const sections = relations.sections = {}; const contributionLinksRelation = contribs => - contribs.map(contrib => - relation('linkContribution', contrib.who, contrib.what)); + contribs + .slice(0, 4) + .map(contrib => + relation('linkContribution', contrib.who, contrib.what)); const additionalFilesSection = additionalFiles => ({ heading: relation('generateContentHeading'), @@ -161,7 +164,7 @@ export default { if (sprawl.enableFlashesAndGames) { const sortedFeatures = - sortChronologically( + sortFlashesChronologically( [track, ...track.otherReleases].flatMap(track => track.featuredInFlashes.map(flash => ({ // These aren't going to be exposed directly, they're processed @@ -169,9 +172,8 @@ export default { flash, track, // These properties are only used for the sort. + act: flash.act, date: flash.date, - name: flash.name, - directory: flash.directory, })))); if (!empty(sortedFeatures)) { @@ -250,6 +252,7 @@ export default { data.albumCoverArtDirectory = album.directory; data.trackCoverArtDirectory = track.directory; data.coverArtFileExtension = track.coverArtFileExtension; + data.coverNeedsReveal = track.artTags.some(t => t.isContentWarning); if (track.coverArtDate && +track.coverArtDate !== +track.date) { data.coverArtDate = track.coverArtDate; @@ -257,6 +260,7 @@ export default { } else if (track.album.hasCoverArt) { data.albumCoverArtDirectory = album.directory; data.coverArtFileExtension = album.coverArtFileExtension; + data.coverNeedsReveal = album.artTags.some(t => t.isContentWarning); } if (!empty(track.additionalFiles)) { @@ -291,6 +295,7 @@ export default { data.coverArtFileExtension, ], }); + content.coverNeedsReveal = data.coverNeedsReveal; } else if (data.hasAlbumCoverArt) { content.cover = relations.cover .slots({ @@ -300,8 +305,10 @@ export default { data.coverArtFileExtension, ], }); + content.coverNeedsReveal = data.coverNeedsReveal; } else { content.cover = null; + content.coverNeedsReveal = null; } content.main = { diff --git a/src/content/dependencies/image.js b/src/content/dependencies/image.js index 822a8996..f9cb00bf 100644 --- a/src/content/dependencies/image.js +++ b/src/content/dependencies/image.js @@ -45,6 +45,7 @@ export default { thumb: {type: 'string'}, + reveal: {type: 'boolean', default: true}, link: {type: 'boolean', default: false}, lazy: {type: 'boolean', default: false}, square: {type: 'boolean', default: false}, @@ -75,7 +76,12 @@ export default { : originalSrc); const willLink = typeof slots.link === 'string' || slots.link; - const willReveal = originalSrc && !empty(data.contentWarnings); + + const willReveal = + slots.reveal && + originalSrc && + !empty(data.contentWarnings); + const willSquare = slots.square; const idOnImg = willLink ? null : slots.id; diff --git a/src/data/things/thing.js b/src/data/things/thing.js index b74f45f5..5004f4e6 100644 --- a/src/data/things/thing.js +++ b/src/data/things/thing.js @@ -264,26 +264,42 @@ export default class Thing extends CacheableObject { // Dynamically inherit a contribution list from some other object, if it // hasn't been overridden on this object. This is handy for solo albums // where all tracks have the same artist, for example. - // - // Note: The arguments of this function aren't currently final! The final - // format will look more like (contribsByRef, parentContribsByRef), e.g. - // ('artistContribsByRef', '@album/artistContribsByRef'). dynamicInheritContribs: ( + // If this property is explicitly false, the contribution list returned + // will always be empty. + nullerProperty, + + // Property holding contributions on the current object. contribsByRefProperty, + + // Property holding corresponding "default" contributions on the parent + // object, which will fallen back to if the object doesn't have its own + // contribs. parentContribsByRefProperty, + + // Data array to search in and "find" function to locate parent object + // (which will be passed the child object and the wiki data array). thingDataProperty, findFn ) => ({ flags: {expose: true}, expose: { - dependencies: [contribsByRefProperty, thingDataProperty, 'artistData'], + dependencies: [ + contribsByRefProperty, + thingDataProperty, + nullerProperty, + 'artistData', + ].filter(Boolean), + compute({ [Thing.instance]: thing, + [nullerProperty]: nuller, [contribsByRefProperty]: contribsByRef, [thingDataProperty]: thingData, artistData, }) { if (!artistData) return []; + if (nuller === false) return []; const refs = contribsByRef ?? findFn(thing, thingData, {mode: 'quiet'})?.[parentContribsByRefProperty]; diff --git a/src/data/things/track.js b/src/data/things/track.js index 1c2013a2..00585c1e 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -245,6 +245,7 @@ export class Track extends Thing { }, artistContribs: Thing.common.dynamicInheritContribs( + null, 'artistContribsByRef', 'artistContribsByRef', 'albumData', @@ -254,6 +255,7 @@ export class Track extends Thing { contributorContribs: Thing.common.dynamicContribs('contributorContribsByRef'), coverArtistContribs: Thing.common.dynamicInheritContribs( + 'hasCoverArt', 'coverArtistContribsByRef', 'trackCoverArtistContribsByRef', 'albumData', diff --git a/src/data/yaml.js b/src/data/yaml.js index 5a6f2031..73450f17 100644 --- a/src/data/yaml.js +++ b/src/data/yaml.js @@ -24,6 +24,7 @@ import { sortAlbumsTracksChronologically, sortAlphabetically, sortChronologically, + sortFlashesChronologically, } from '../util/wiki-data.js'; import find, {bindFind} from '../util/find.js'; @@ -1154,6 +1155,7 @@ export function sortWikiDataArrays(wikiData) { Object.assign(wikiData, { albumData: sortChronologically(wikiData.albumData.slice()), trackData: sortAlbumsTracksChronologically(wikiData.trackData.slice()), + flashData: sortFlashesChronologically(wikiData.flashData.slice()), }); // Re-link data arrays, so that every object has the new, sorted versions. diff --git a/src/listing-spec.js b/src/listing-spec.js index 08799f2f..36637ee0 100644 --- a/src/listing-spec.js +++ b/src/listing-spec.js @@ -12,6 +12,7 @@ import { sortAlphabetically, sortByDate, sortChronologically, + sortFlashesChronologically, } from './util/wiki-data.js'; const listingSpec = []; @@ -775,7 +776,7 @@ listingSpec.push({ wikiInfo.enableFlashesAndGames, data: ({wikiData: {flashData}}) => - sortChronologically(flashData.slice()) + sortFlashesChronologically(flashData.slice()) .map(flash => ({ flash, tracks: flash.featuredTracks, diff --git a/src/page/artist.js b/src/page/artist.js index 852310d3..ad365161 100644 --- a/src/page/artist.js +++ b/src/page/artist.js @@ -2,19 +2,6 @@ // // NB: See artist-alias.js for artist alias redirect pages. -import { - bindOpts, - empty, - unique, -} from '../util/sugar.js'; - -import { - chunkByProperties, - getTotalDuration, - sortAlbumsTracksChronologically, - sortChronologically, -} from '../util/wiki-data.js'; - export const description = `per-artist info & artwork gallery pages`; export function targets({wikiData}) { diff --git a/src/static/site4.css b/src/static/site4.css index 08512559..28a4924d 100644 --- a/src/static/site4.css +++ b/src/static/site4.css @@ -1559,12 +1559,12 @@ html[data-language-code="preview-en"][data-url-key="localized.home"] #content z-index: 2; } - html[data-url-key="localized.home"] .layout-columns.has-one-sidebar .grid-listing > .grid-item:not(:nth-child(n+10)) { + html[data-url-key="localized.home"] .layout-columns.has-one-sidebar .grid-listing > .grid-item:not(:nth-child(n+7)) { flex-basis: 23%; margin: 15px; } - html[data-url-key="localized.home"] .layout-columns.has-one-sidebar .grid-listing > .grid-item:nth-child(n+10) { + html[data-url-key="localized.home"] .layout-columns.has-one-sidebar .grid-listing > .grid-item:nth-child(n+7) { flex-basis: 18%; margin: 10px; } diff --git a/src/upd8.js b/src/upd8.js index ed54ec47..366dc21b 100755 --- a/src/upd8.js +++ b/src/upd8.js @@ -87,7 +87,7 @@ import FileSizePreloader from './file-size-preloader.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const CACHEBUST = 19; +const CACHEBUST = 20; let COMMIT; try { diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js index 0eb86a1e..89c621c5 100644 --- a/src/util/wiki-data.js +++ b/src/util/wiki-data.js @@ -181,6 +181,7 @@ export function sortByName(data, { } export function sortByDate(data, { + latestFirst = false, getDate = (o) => o.date, } = {}) { return data.sort((a, b) => { @@ -191,7 +192,7 @@ export function sortByDate(data, { // together in the same array. If that's the case, we put all items // without dates at the end. if (ad && bd) { - return ad - bd; + return (latestFirst ? bd - ad : ad - bd); } else if (ad) { return -1; } else if (bd) { @@ -206,35 +207,52 @@ export function sortByDate(data, { }); } -export function sortByPositionInAlbum(data) { +export function sortByPositionInParent(data, { + getParent, + getChildren, +}) { return data.sort((a, b) => { - const aa = a.album; - const ba = b.album; + const parentA = getParent(a); + const parentB = getParent(b); - // Don't change the sort when the two tracks are from separate albums. - // This function doesn't change the order of albums or try to "merge" - // two separated chunks of tracks from the same album together. - if (aa !== ba) { + // Don't change the sort when the two items are from separate parents. + // This function doesn't change the order of parents or try to "merge" + // two separated chunks of items from the same parent together. + if (parentA !== parentB) { return 0; } - // Don't change the sort when only one (or neither) item is actually - // a track (i.e. has an album). - if (!aa || !ba) { + // Don't change the sort when either (or both) of the items doesn't + // even have a parent (e.g. it's the passed data is a mixed array of + // children and parents). + if (!parentA || !parentB) { return 0; } - const ai = aa.tracks.indexOf(a); - const bi = ba.tracks.indexOf(b); + const indexA = getChildren(parentA).indexOf(a); + const indexB = getChildren(parentB).indexOf(b); - // There's no reason this two-way reference (a track's album and the - // album's track list) should be broken, but if for any reason it is, - // don't change the sort. - if (ai === -1 || bi === -1) { + // If the getParent/getChildren relationship doesn't go both ways for + // some reason, don't change the sort. + if (indexA === -1 || indexB === -1) { return 0; } - return ai - bi; + return indexA - indexB; + }); +} + +export function sortByPositionInAlbum(data) { + return sortByPositionInParent(data, { + getParent: track => track.album, + getChildren: album => album.tracks, + }); +} + +export function sortByPositionInFlashAct(data) { + return sortByPositionInParent(data, { + getParent: flash => flash.act, + getChildren: act => act.flashes, }); } @@ -242,7 +260,7 @@ export function sortByPositionInAlbum(data) { // set of arbitrary given conditions is true first. If no conditions are met // for a given item, it's moved over to the end! export function sortByConditions(data, conditions) { - data.sort((a, b) => { + return data.sort((a, b) => { const ai = conditions.findIndex((f) => f(a)); const bi = conditions.findIndex((f) => f(b)); @@ -292,18 +310,8 @@ export function sortChronologically(data, { getName, getDate, } = {}) { - if (latestFirst) { - // Double reverse: Since we reverse after sorting by date, also reverse - // after sorting A-Z, so the second reverse restores A-Z relative - // positioning (for entries with the same date). - sortAlphabetically(data, {getDirectory, getName}); - data.reverse(); - sortByDate(data, {getDate}); - data.reverse(); - } else { - sortAlphabetically(data, {getDirectory, getName}); - sortByDate(data, {getDate}); - } + sortAlphabetically(data, {getDirectory, getName}); + sortByDate(data, {latestFirst, getDate}); return data; } @@ -316,6 +324,7 @@ export function sortChronologically(data, { // // This function also works for data lists which contain only tracks. export function sortAlbumsTracksChronologically(data, { + latestFirst = false, getDate, } = {}) { // Sort albums before tracks... @@ -333,7 +342,39 @@ export function sortAlbumsTracksChronologically(data, { // released on the same date, they'll still be grouped together by album, // and tracks within an album will retain their relative positioning (i.e. // stay in the same order as part of the album's track listing). - sortByDate(data, {getDate}); + sortByDate(data, {latestFirst, getDate}); + + return data; +} + +export function sortFlashesChronologically(data, { + latestFirst = false, + getDate, +} = {}) { + // Flash acts don't actually have any identifying properties because they + // don't have dedicated pages (yet), so don't have a directory. Make up a + // fake key identifying them so flashes can be grouped together. + const flashActs = new Set(data.map(flash => flash.act)); + const flashActIdentifiers = new Map(); + + let counter = 0; + for (const act of flashActs) { + flashActIdentifiers.set(act, ++counter); + } + + // Group flashes by act... + data.sort((a, b) => { + return flashActIdentifiers.get(a.act) - flashActIdentifiers.get(b.act); + }); + + // Sort flashes by position in act... + sortByPositionInFlashAct(data); + + // ...and finally sort by date. If flashes from more than one act were + // released on the same date, they'll still be grouped together by act, + // and flashes within an act will retain their relative positioning (i.e. + // stay in the same order as the act's flash listing). + sortByDate(data, {latestFirst, getDate}); return data; } |