diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/content/dependencies/generateAbsoluteDatetimestamp.js | 12 | ||||
| -rw-r--r-- | src/content/dependencies/generateMusicVideo.js | 44 | ||||
| -rw-r--r-- | src/content/dependencies/generateMusicVideoReleaseLine.js | 61 | ||||
| -rw-r--r-- | src/content/dependencies/generateSingleArtworkColumn.js | 16 | ||||
| -rw-r--r-- | src/content/dependencies/generateTrackArtworkColumn.js | 2 | ||||
| -rw-r--r-- | src/content/dependencies/generateTrackInfoPage.js | 2 | ||||
| -rw-r--r-- | src/content/dependencies/listTracksWithExtra.js | 3 | ||||
| -rw-r--r-- | src/content/dependencies/listTracksWithMusicVideos.js | 9 | ||||
| -rw-r--r-- | src/data/things/music-video.js | 15 | ||||
| -rw-r--r-- | src/data/things/track.js | 12 | ||||
| -rw-r--r-- | src/listing-spec.js | 9 | ||||
| -rw-r--r-- | src/static/css/site.css | 16 | ||||
| -rw-r--r-- | src/strings-default.yaml | 40 |
13 files changed, 191 insertions, 50 deletions
diff --git a/src/content/dependencies/generateAbsoluteDatetimestamp.js b/src/content/dependencies/generateAbsoluteDatetimestamp.js index d006374a..52b524e0 100644 --- a/src/content/dependencies/generateAbsoluteDatetimestamp.js +++ b/src/content/dependencies/generateAbsoluteDatetimestamp.js @@ -21,6 +21,7 @@ export default { 'year', 'minimal-difference', 'year-difference', + 'full-difference', ]), default: 'full', }, @@ -78,6 +79,17 @@ export default { label = language.formatYear(data.date); tooltip = language.formatDate(data.date); } + + break; + } + + case 'full-difference': { + if (data.date.toDateString() === data.contextDate?.toDateString()) { + return html.blank(); + } + + label = language.formatDate(data.date); + break; } } diff --git a/src/content/dependencies/generateMusicVideo.js b/src/content/dependencies/generateMusicVideo.js index a61cd5b7..e83fdf80 100644 --- a/src/content/dependencies/generateMusicVideo.js +++ b/src/content/dependencies/generateMusicVideo.js @@ -1,5 +1,5 @@ export default { - relations: (relation, musicVideo) => ({ + relations: (relation, musicVideo, thing) => ({ image: relation('image', { path: musicVideo.path, @@ -7,14 +7,14 @@ export default { dimensions: musicVideo.coverArtDimensions, }), - artistCredit: - relation('generateArtistCredit', musicVideo.artistContribs, []), + releaseLine: + relation('generateMusicVideoReleaseLine', musicVideo, thing), contributorCredit: relation('generateArtistCredit', musicVideo.contributorContribs, []), }), - data: (musicVideo) => ({ + data: (musicVideo, _track) => ({ label: musicVideo.label, @@ -45,33 +45,25 @@ export default { {[html.joinChildren]: html.tag('br')}, [ - language.encapsulate(capsule, 'by', workingCapsule => { - const additionalStringOptions = {}; + html.tag('span', {class: 'release-line'}, + {[html.onlyIfContent]: true}, - if (data.label) { - workingCapsule += '.customLabel'; - additionalStringOptions.label = data.label; - } + relations.releaseLine), - return relations.artistCredit.slots({ - normalStringKey: workingCapsule, - additionalStringOptions, + language.encapsulate(capsule, 'contributorsLine', capsule => + language.$(capsule, { + [language.onlyIfOptions]: ['credit'], - showAnnotation: true, - showChronology: true, + credit: + relations.contributorCredit.slots({ + normalStringKey: language.encapsulate(capsule, 'credit'), - chronologyKind: 'musicVideo', - }); - }), + showAnnotation: true, + showChronology: true, - relations.contributorCredit.slots({ - normalStringKey: language.encapsulate(capsule, 'contributors'), - - showAnnotation: true, - showChronology: true, - - chronologyKind: 'musicVideoContribution', - }), + chronologyKind: 'musicVideoContribution', + }), + })), ]), ])), }; diff --git a/src/content/dependencies/generateMusicVideoReleaseLine.js b/src/content/dependencies/generateMusicVideoReleaseLine.js new file mode 100644 index 00000000..e4e196e9 --- /dev/null +++ b/src/content/dependencies/generateMusicVideoReleaseLine.js @@ -0,0 +1,61 @@ +export default { + relations: (relation, musicVideo, thing) => ({ + datetimestamp: + relation('generateAbsoluteDatetimestamp', musicVideo.date, thing.date), + + artistCredit: + relation('generateArtistCredit', musicVideo.artistContribs, []), + }), + + data: (data) => ({ + label: + (data.label !== 'Music video' + ? data.label + : null), + }), + + generate(data, relations, {html, language}) { + const {artistCredit, datetimestamp} = relations; + const capsule = language.encapsulate('misc.musicVideo'); + + datetimestamp.setSlot('style', 'full-difference'); + + let artistsLineCapsule = language.encapsulate(capsule, 'artistsLine'); + let artistsLineOptions = {[language.onlyIfOptions]: ['credit']}; + + if (data.label) { + artistsLineCapsule += '.customLabel'; + artistsLineOptions.label = data.label; + } + + if (!html.isBlank(datetimestamp)) { + artistsLineCapsule += '.withDate'; + artistsLineOptions.date = datetimestamp; + } + + artistsLineOptions.credit = + html.tag('span', {class: 'by'}, + {[html.onlyIfContent]: true}, + + artistCredit.slots({ + normalStringKey: language.encapsulate(capsule, 'artistsLine.credit'), + + showAnnotation: true, + showChronology: true, + + chronologyKind: 'musicVideo', + })); + + const artistsLine = language.$(artistsLineCapsule, artistsLineOptions); + + if (!html.isBlank(artistsLine)) { + return artistsLine; + } + + if (!html.isBlank(datetimestamp)) { + return language.$(capsule, 'date', {date: datetimestamp}); + } + + return html.blank(); + }, +} diff --git a/src/content/dependencies/generateSingleArtworkColumn.js b/src/content/dependencies/generateSingleArtworkColumn.js new file mode 100644 index 00000000..32c448ad --- /dev/null +++ b/src/content/dependencies/generateSingleArtworkColumn.js @@ -0,0 +1,16 @@ +export default { + relations: (relation, track) => ({ + albumArtworkColumn: + relation('generateAlbumArtworkColumn', track.album), + + trackMusicVideos: + track.musicVideos.map(musicVideo => + relation('generateMusicVideo', musicVideo, track)), + }), + + generate: (relations, {html}) => + html.tags([ + relations.albumArtworkColumn, + relations.trackMusicVideos, + ]), +}; diff --git a/src/content/dependencies/generateTrackArtworkColumn.js b/src/content/dependencies/generateTrackArtworkColumn.js index dde37376..feaed604 100644 --- a/src/content/dependencies/generateTrackArtworkColumn.js +++ b/src/content/dependencies/generateTrackArtworkColumn.js @@ -13,7 +13,7 @@ export default { trackMusicVideos: track.musicVideos.map(musicVideo => - relation('generateMusicVideo', musicVideo)), + relation('generateMusicVideo', musicVideo, track)), }), generate: (relations, {html}) => diff --git a/src/content/dependencies/generateTrackInfoPage.js b/src/content/dependencies/generateTrackInfoPage.js index 0937c42c..77adff02 100644 --- a/src/content/dependencies/generateTrackInfoPage.js +++ b/src/content/dependencies/generateTrackInfoPage.js @@ -65,7 +65,7 @@ export default { artworkColumn: (query.firstTrackInSingle - ? relation('generateAlbumArtworkColumn', track.album) + ? relation('generateSingleArtworkColumn', track) : relation('generateTrackArtworkColumn', track)), contentHeading: diff --git a/src/content/dependencies/listTracksWithExtra.js b/src/content/dependencies/listTracksWithExtra.js index 09d8ee21..27f03ee9 100644 --- a/src/content/dependencies/listTracksWithExtra.js +++ b/src/content/dependencies/listTracksWithExtra.js @@ -52,6 +52,7 @@ export default { slots: { hash: {type: 'string'}, + showAlbumDates: {type: 'boolean', default: true}, }, generate(data, relations, slots, {language}) { @@ -63,7 +64,7 @@ export default { albumLink: relations.albumLinks, date: data.dates, }).map(({albumLink, date}) => - (date + (slots.showAlbumDates && date ? { stringsKey: 'withDate', album: albumLink, diff --git a/src/content/dependencies/listTracksWithMusicVideos.js b/src/content/dependencies/listTracksWithMusicVideos.js new file mode 100644 index 00000000..e7aa1f5e --- /dev/null +++ b/src/content/dependencies/listTracksWithMusicVideos.js @@ -0,0 +1,9 @@ +export default { + relations: (relation, spec) => + ({page: relation('listTracksWithExtra', spec, 'musicVideos', 'array')}), + + generate: (relations) => + relations.page.slots({ + showAlbumDates: false, + }), +}; diff --git a/src/data/things/music-video.js b/src/data/things/music-video.js index 267349e8..6c1e3ba6 100644 --- a/src/data/things/music-video.js +++ b/src/data/things/music-video.js @@ -5,7 +5,7 @@ import {input, V} from '#composite'; import find from '#find'; import Thing from '#thing'; import {isDate, isStringNonEmpty, isURL} from '#validators'; -import {parseContributors} from '#yaml'; +import {parseContributors, parseDate} from '#yaml'; import {exposeConstant, exposeUpdateValueOrContinue} from '#composite/control-flow'; @@ -72,21 +72,14 @@ export class MusicVideo extends Thing { fields: { 'Label': {property: 'label'}, 'Directory': {property: 'unqualifiedDirectory'}, - 'Date': {property: 'date'}, + 'Date': {property: 'date', transform: parseDate}, 'URL': {property: 'url'}, 'Cover Art File Extension': {property: 'coverArtFileExtension'}, 'Cover Art Dimensions': {property: 'coverArtDimensions'}, - 'Artists': { - property: 'artistContribs', - transform: parseContributors, - }, - - 'Contributors': { - property: 'contributorContribs', - transform: parseContributors, - }, + 'Artists': {property: 'artistContribs', transform: parseContributors}, + 'Contributors': {property: 'contributorContribs', transform: parseContributors}, }, }; diff --git a/src/data/things/track.js b/src/data/things/track.js index 8652fbdf..5b40ca4d 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -492,7 +492,17 @@ export class Track extends Thing { // > Update & expose - Music videos - musicVideos: thingList(V(MusicVideo)), + musicVideos: [ + exposeUpdateValueOrContinue(), + + // TODO: Same situation as lyrics. Inherited music videos don't set + // the proper .thing property back to this track... but then, it needs + // to keep a reference to its original .thing to get its proper path, + // so maybe this is okay... + inheritFromMainRelease(), + + thingList(V(MusicVideo)), + ], // > Update & expose - Additional files diff --git a/src/listing-spec.js b/src/listing-spec.js index a301845b..019b34ab 100644 --- a/src/listing-spec.js +++ b/src/listing-spec.js @@ -178,7 +178,14 @@ listingSpec.push({ directory: 'tracks/with-lyrics', stringsKey: 'listTracks.withLyrics', contentFunction: 'listTracksWithLyrics', - seeAlso: ['tracks/needing-lyrics'], + seeAlso: ['tracks/needing-lyrics', 'tracks/with-music-videos'], +}); + +listingSpec.push({ + directory: 'tracks/with-music-videos', + stringsKey: 'listTracks.withMusicVideos', + contentFunction: 'listTracksWithMusicVideos', + seeAlso: ['tracks/with-lyrics'], }); listingSpec.push({ diff --git a/src/static/css/site.css b/src/static/css/site.css index d57f5712..1b4f3a84 100644 --- a/src/static/css/site.css +++ b/src/static/css/site.css @@ -1929,8 +1929,7 @@ p.image-details.origin-details .filename-line { align-items: center; } -.music-video .image-link:hover::after, -.music-video .image-link:focus::after { +.music-video .image-link:hover::after { font-size: 1.4em; background: #0006; } @@ -1941,11 +1940,20 @@ p.image-details.origin-details .filename-line { box-shadow: 0 0 4px inset black; } -.music-video .image-link:hover .image, -.music-video .image-link:focus .image { +.music-video .image-link:hover .image { transform: scale(1.02); } +.music-video .release-line { + display: block; + padding-left: 1.2ch; + text-indent: -1.2ch; +} + +.music-video .release-line > * { + text-indent: 0; +} + .album-art-info { font-size: 0.8em; border: 2px solid var(--deep-color); diff --git a/src/strings-default.yaml b/src/strings-default.yaml index dc6bffdd..4ddd6e48 100644 --- a/src/strings-default.yaml +++ b/src/strings-default.yaml @@ -988,16 +988,36 @@ misc: # musicVideo: # Strings for music videos, which are presented in a very similar - # fashion as cover artworks. + # fashion as cover artworks, although the strings are structured + # a bit differently. musicVideo: label: "Music video!" label.customLabel: "{LABEL}!" - by: "Music video by {ARTISTS}" - by.customLabel: "{LABEL} by {ARTISTS}" + artistsLine: >- + Music video {CREDIT} - contributors: "Contributors: {ARTISTS}" + artistsLine.customLabel: >- + {LABEL} {CREDIT} + + artistsLine.withDate: >- + Music video ({DATE}) {CREDIT} + + artistsLine.customLabel.withDate: >- + {LABEL} ({DATE}) {CREDIT} + + artistsLine.credit: >- + by {ARTISTS} + + date: >- + Released {DATE} + + contributorsLine: >- + Contributors: {CREDIT} + + contributorsLine.credit: >- + {ARTISTS} # coverGrid: # Generic strings for various sorts of gallery grids, displayed @@ -2305,6 +2325,18 @@ listingPage: title.withDate: "{ALBUM} ({DATE})" item: "{TRACK}" + # listTracks.withMusicVideos: + # The same as withLyrics, but for music videos. + + withMusicVideos: + title: "Tracks - with Music Videos" + title.short: "...with Music Videos" + + chunk: + title: "{ALBUM}" + title.withDate: "{ALBUM} ({DATE})" + item: "{TRACK}" + # listTracks.withSheetMusicFiles: # List tracks, chunked by album (which are sorted by date, # falling back alphabetically) and in their usual track order, |