From 112a840bdf69bfba5aae893e92b0b20c4a4884fd Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 2 Jul 2025 17:43:34 -0300 Subject: data, content: singles --- src/content/dependencies/generateAlbumSidebar.js | 15 +++++++---- .../generateAlbumSidebarTrackListBox.js | 10 ++++++-- .../generateAlbumSidebarTrackSection.js | 23 +++++++++++++---- src/content/dependencies/generateTrackInfoPage.js | 30 +++++++++++++++++----- src/content/dependencies/linkAlbum.js | 10 +++++--- src/data/things/album.js | 25 +++++++++++++++--- src/page/album.js | 25 +++++++++++------- 7 files changed, 105 insertions(+), 33 deletions(-) diff --git a/src/content/dependencies/generateAlbumSidebar.js b/src/content/dependencies/generateAlbumSidebar.js index 7cf689cc..464274e3 100644 --- a/src/content/dependencies/generateAlbumSidebar.js +++ b/src/content/dependencies/generateAlbumSidebar.js @@ -108,24 +108,29 @@ export default { : null), }), - data: (_query, _sprawl, _album, track) => ({ + data: (_query, _sprawl, album, track) => ({ isAlbumPage: !track, isTrackPage: !!track, + + albumStyle: album.style, }), generate(data, relations, {html}) { + const presentGroupsLikeAlbum = + data.isAlbumPage || + data.albumStyle === 'single'; + for (const box of [ ...relations.groupBoxes, ...relations.seriesBoxes.flat(), ...relations.disconnectedSeriesBoxes, ]) { - box.setSlot('mode', - data.isAlbumPage ? 'album' : 'track'); + box.setSlot('mode', presentGroupsLikeAlbum ? 'album' : 'track'); } return relations.sidebar.slots({ boxes: [ - data.isAlbumPage && [ + presentGroupsLikeAlbum && [ relations.disconnectedSeriesBoxes, stitchArrays({ @@ -150,7 +155,7 @@ export default { data.isTrackPage && relations.laterTrackReleaseBoxes, - data.isTrackPage && + !presentGroupsLikeAlbum && relations.conjoinedBox.slots({ attributes: {class: 'conjoined-group-sidebar-box'}, boxes: diff --git a/src/content/dependencies/generateAlbumSidebarTrackListBox.js b/src/content/dependencies/generateAlbumSidebarTrackListBox.js index 3a244e3a..36d1e6b6 100644 --- a/src/content/dependencies/generateAlbumSidebarTrackListBox.js +++ b/src/content/dependencies/generateAlbumSidebarTrackListBox.js @@ -19,12 +19,18 @@ export default { relation('generateAlbumSidebarTrackSection', album, track, trackSection)), }), - generate: (relations, {html}) => + data: (album) => ({ + albumStyle: album.style, + }), + + generate: (data, relations, {html}) => relations.box.slots({ attributes: {class: 'track-list-sidebar-box'}, content: [ - html.tag('h1', relations.albumLink), + html.tag('h1', {[html.onlyIfSiblings]: true}, + relations.albumLink), + relations.trackSections, ], }) diff --git a/src/content/dependencies/generateAlbumSidebarTrackSection.js b/src/content/dependencies/generateAlbumSidebarTrackSection.js index dae5fa03..a158d2d4 100644 --- a/src/content/dependencies/generateAlbumSidebarTrackSection.js +++ b/src/content/dependencies/generateAlbumSidebarTrackSection.js @@ -22,10 +22,12 @@ export default { !empty(trackSection.tracks); data.isTrackPage = !!track; + data.albumStyle = album.style; data.name = trackSection.name; data.color = trackSection.color; data.isDefaultTrackSection = trackSection.isDefaultTrackSection; + data.hasSiblingSections = album.trackSections.length > 1; data.firstTrackNumber = (data.hasTrackNumbers @@ -115,6 +117,21 @@ export default { : trackLink), }))); + const list = + (data.hasTrackNumbers + ? html.tag('ol', + {start: data.firstTrackNumber}, + trackListItems) + : html.tag('ul', trackListItems)); + + if (data.albumStyle === 'single' && !data.hasSiblingSections) { + if (trackListItems.length <= 1) { + return html.blank(); + } else { + return list; + } + } + return html.tag('details', data.includesCurrentTrack && {class: 'current'}, @@ -157,11 +174,7 @@ export default { return language.$(workingCapsule, workingOptions); })))), - (data.hasTrackNumbers - ? html.tag('ol', - {start: data.firstTrackNumber}, - trackListItems) - : html.tag('ul', trackListItems)), + list, ]); }, }; diff --git a/src/content/dependencies/generateTrackInfoPage.js b/src/content/dependencies/generateTrackInfoPage.js index 6c16ce27..1a5f84be 100644 --- a/src/content/dependencies/generateTrackInfoPage.js +++ b/src/content/dependencies/generateTrackInfoPage.js @@ -48,6 +48,9 @@ export default { navLinks: relation('generateTrackNavLinks', track), + albumNavLink: + relation('linkAlbum', track.album), + albumNavAccent: relation('generateAlbumNavAccent', track.album, track), @@ -125,6 +128,10 @@ export default { color: track.color, + + singleTrackSingle: + track.album.style === 'single' && + track.album.tracks.length === 1, }), generate: (data, relations, {html, language}) => @@ -376,17 +383,28 @@ export default { ], navLinkStyle: 'hierarchical', - navLinks: html.resolve(relations.navLinks), + navLinks: + (data.singleTrackSingle + ? [ + {auto: 'home'}, + {html: relations.albumNavLink}, + ] + : html.resolve(relations.navLinks)), navBottomRowContent: - relations.albumNavAccent.slots({ - showTrackNavigation: true, - showExtraLinks: false, - }), + (data.singleTrackSingle + ? relations.albumNavAccent.slots({ + showTrackNavigation: false, + showExtraLinks: true, + }) + : relations.albumNavAccent.slots({ + showTrackNavigation: true, + showExtraLinks: false, + })), secondaryNav: relations.secondaryNav - .slot('mode', 'track'), + .slot('mode', data.singleTrackSingle ? 'album' : 'track'), leftSidebar: relations.sidebar, diff --git a/src/content/dependencies/linkAlbum.js b/src/content/dependencies/linkAlbum.js index 36b0d13a..cdfe65d3 100644 --- a/src/content/dependencies/linkAlbum.js +++ b/src/content/dependencies/linkAlbum.js @@ -1,8 +1,12 @@ export default { - contentDependencies: ['linkThing'], + contentDependencies: ['linkThing', 'linkTrack'], - relations: (relation, album) => - ({link: relation('linkThing', 'localized.album', album)}), + relations: (relation, album) => ({ + link: + (album.style === 'single' + ? relation('linkTrack', album.tracks[0]) + : relation('linkThing', 'localized.album', album)), + }), generate: (relations) => relations.link, }; diff --git a/src/data/things/album.js b/src/data/things/album.js index 51698148..a922e565 100644 --- a/src/data/things/album.js +++ b/src/data/things/album.js @@ -10,7 +10,7 @@ import {traverse} from '#node-utils'; import {sortAlbumsTracksChronologically, sortChronologically} from '#sort'; import {empty} from '#sugar'; import Thing from '#thing'; -import {isColor, isDate, isDirectory, isNumber} from '#validators'; +import {is, isColor, isDate, isDirectory, isNumber} from '#validators'; import { parseAdditionalFiles, @@ -25,12 +25,17 @@ import { parseWallpaperParts, } from '#yaml'; -import {exitWithoutDependency, exposeDependency, exposeUpdateValueOrContinue} - from '#composite/control-flow'; import {withPropertyFromObject} from '#composite/data'; import {exitWithoutArtwork, withDirectory, withHasArtwork} from '#composite/wiki-data'; +import { + exitWithoutDependency, + exposeConstant, + exposeDependency, + exposeUpdateValueOrContinue, +} from '#composite/control-flow'; + import { color, commentatorArtists, @@ -102,6 +107,19 @@ export class Album extends Thing { alwaysReferenceTracksByDirectory: flag(false), suffixTrackDirectories: flag(false), + style: [ + exposeUpdateValueOrContinue({ + validate: input.value(is(...[ + 'album', + 'single', + ])), + }), + + exposeConstant({ + value: input.value('album'), + }), + ], + bandcampAlbumIdentifier: simpleString(), bandcampArtworkIdentifier: simpleString(), @@ -541,6 +559,7 @@ export class Album extends Thing { 'Suffix Track Directories': {property: 'suffixTrackDirectories'}, 'Always Reference By Directory': {property: 'alwaysReferenceByDirectory'}, 'Always Reference Tracks By Directory': {property: 'alwaysReferenceTracksByDirectory'}, + 'Style': {property: 'style'}, 'Bandcamp Album ID': { property: 'bandcampAlbumIdentifier', diff --git a/src/page/album.js b/src/page/album.js index 696e2854..e585618c 100644 --- a/src/page/album.js +++ b/src/page/album.js @@ -8,15 +8,22 @@ export function targets({wikiData}) { export function pathsForTarget(album) { return [ - { - type: 'page', - path: ['album', album.directory], - - contentFunction: { - name: 'generateAlbumInfoPage', - args: [album], - }, - }, + (album.style === 'single' + ? { + type: 'redirect', + fromPath: ['album', album.directory], + toPath: ['track', album.tracks[0].directory], + title: album.name, + } + : { + type: 'page', + path: ['album', album.directory], + + contentFunction: { + name: 'generateAlbumInfoPage', + args: [album], + }, + }), { type: 'page', -- cgit 1.3.0-6-gf8a5