diff options
| -rw-r--r-- | src/content/dependencies/generateDividedFeaturedInFlashesList.js | 142 | ||||
| -rw-r--r-- | src/content/dependencies/generateDividedTrackList.js | 4 | ||||
| -rw-r--r-- | src/content/dependencies/generateTrackFeaturedInFlashesList.js (renamed from src/content/dependencies/generateTrackInfoPageFeaturedByFlashesList.js) | 32 | ||||
| -rw-r--r-- | src/content/dependencies/generateTrackInfoPage.js | 2 | ||||
| -rw-r--r-- | src/content/dependencies/listTracksInFlashesByAlbum.js | 2 | ||||
| -rw-r--r-- | src/data/things/Track.js | 39 | ||||
| -rw-r--r-- | src/data/things/WikiInfo.js | 30 | ||||
| -rw-r--r-- | src/strings-default.yaml | 11 |
8 files changed, 223 insertions, 39 deletions
diff --git a/src/content/dependencies/generateDividedFeaturedInFlashesList.js b/src/content/dependencies/generateDividedFeaturedInFlashesList.js new file mode 100644 index 00000000..93e29991 --- /dev/null +++ b/src/content/dependencies/generateDividedFeaturedInFlashesList.js @@ -0,0 +1,142 @@ +import {empty, filterMultipleArrays, stitchArrays} from '#sugar'; + +export default { + sprawl: ({flashSideData, wikiInfo}) => ({ + enableFlashesAndGames: + wikiInfo.enableFlashesAndGames, + + divideFlashListsBySides: + wikiInfo.divideFlashListsBySides, + + allSides: + flashSideData, + }), + + query(sprawl, features, _contextTrack) { + if (!sprawl.enableFlashesAndGames) { + return {dividingSides: [], dividedFeatures: []}; + } + + const {allSides} = sprawl; + + const divisions = new Map(); + const dividingSideIndices = []; + for (const {side, label} of sprawl.divideFlashListsBySides) { + divisions.set(side, {label, features: []}); + dividingSideIndices.push(allSides.indexOf(side)); + } + + for (const feature of features) { + const sideIndex = + allSides.indexOf(feature.flash.side); + + const closestDividingSideIndex = + dividingSideIndices.findLast(i => i <= sideIndex); + + const closestDividingSide = + allSides.at(closestDividingSideIndex); + + if (closestDividingSide) { + divisions.get(closestDividingSide).features.push(feature); + } + } + + const dividingSides = Array.from(divisions.keys()); + const dividingLabels = Array.from(divisions.values()).map(({label}) => label); + const dividedFeatures = Array.from(divisions.values()).map(({features}) => features); + + filterMultipleArrays( + dividingSides, + dividingLabels, + dividedFeatures, + (_side, _label, dividedFeatures) => !empty(dividedFeatures)); + + return {dividingSides, dividingLabels, dividedFeatures}; + }, + + relations: (relation, query, sprawl, features, contextTrack) => ({ + flatList: + (empty(sprawl.divideFlashListsBySides) + ? relation('generateTrackFeaturedInFlashesList', features, contextTrack) + : null), + + contentHeading: + relation('generateContentHeading'), + + dividingSideLinks: + query.dividingSides + .map(side => relation('linkFlashSide', side)), + + dividedFlashLists: + query.dividedFeatures + .map(features => relation('generateTrackFeaturedInFlashesList', features, contextTrack)), + }), + + data: (query, _sprawl, _tracks) => ({ + dividingSideNames: + query.dividingSides + .map(side => side.name), + + dividingLabels: + query.dividingLabels, + }), + + slots: { + headingString: { + type: 'string', + }, + }, + + generate(data, relations, slots, {html, language}) { + if (relations.flatList) { + return relations.flatList; + } + + stitchArrays({ + sideLink: relations.dividingSideLinks, + label: data.dividingLabels, + }).forEach(({sideLink, label}) => { + sideLink.setSlot('color', false); + + if (label) { + sideLink.setSlot('content', language.sanitize(label)); + } + }); + + return ( + html.tag('dl', {class: 'division-list'}, + {[html.onlyIfContent]: true}, + + language.encapsulate('flashList', listCapsule => + stitchArrays({ + sideLink: relations.dividingSideLinks, + flashList: relations.dividedFlashLists, + sideName: data.dividingSideNames, + label: data.dividingLabels, + }).map(({sideLink, flashList, sideName, label}) => [ + language.encapsulate(listCapsule, 'underSide', capsule => + (slots.headingString + ? relations.contentHeading.clone().slots({ + tag: 'dt', + + title: + language.$(capsule, {side: sideLink}), + + stickyTitle: + language.$(slots.headingString, 'sticky', 'fromGroup', { + side: + (label + ? language.sanitize(label) + : language.sanitize(sideName)), + }), + }) + + : html.tag('dt', + language.$(capsule, { + side: sideLink, + })))), + + html.tag('dd', flashList), + ])))); + }, +}; diff --git a/src/content/dependencies/generateDividedTrackList.js b/src/content/dependencies/generateDividedTrackList.js index f255fbaf..ea349ec8 100644 --- a/src/content/dependencies/generateDividedTrackList.js +++ b/src/content/dependencies/generateDividedTrackList.js @@ -100,7 +100,7 @@ export default { title: language.$(capsule, { - group: groupLink + group: groupLink.slot('color', false), }), stickyTitle: @@ -110,7 +110,7 @@ export default { }) : html.tag('dt', language.$(capsule, { - group: groupLink + group: groupLink.slot('color', false), })))), html.tag('dd', trackList), diff --git a/src/content/dependencies/generateTrackInfoPageFeaturedByFlashesList.js b/src/content/dependencies/generateTrackFeaturedInFlashesList.js index cd7bb014..f13368d1 100644 --- a/src/content/dependencies/generateTrackInfoPageFeaturedByFlashesList.js +++ b/src/content/dependencies/generateTrackFeaturedInFlashesList.js @@ -1,36 +1,14 @@ -import {sortFlashesChronologically} from '#sort'; import {stitchArrays} from '#sugar'; export default { - sprawl: ({wikiInfo}) => ({ - enableFlashesAndGames: - wikiInfo.enableFlashesAndGames, - }), - - query: (sprawl, track) => ({ - sortedFeatures: - (sprawl.enableFlashesAndGames - ? sortFlashesChronologically( - track.allReleases.flatMap(track => - track.featuredInFlashes.map(flash => ({ - flash, - track, - - // These properties are only used for the sort. - act: flash.act, - date: flash.date, - })))) - : []), - }), - - relations: (relation, query, _sprawl, track) => ({ + relations: (relation, features, track) => ({ flashLinks: - query.sortedFeatures + features .map(({flash}) => relation('linkFlash', flash)), trackLinks: - query.sortedFeatures - .map(({track: directlyFeaturedTrack}) => + features + .map(({as: directlyFeaturedTrack}) => (directlyFeaturedTrack === track ? null : directlyFeaturedTrack.name === track.name @@ -47,7 +25,7 @@ export default { trackLink: relations.trackLinks, }).map(({flashLink, trackLink}) => { const attributes = html.attributes(); - const parts = ['releaseInfo.flashesThatFeature.item']; + const parts = ['flashList.item']; const options = {flash: flashLink}; if (trackLink) { diff --git a/src/content/dependencies/generateTrackInfoPage.js b/src/content/dependencies/generateTrackInfoPage.js index 9ff47ec3..5dce680b 100644 --- a/src/content/dependencies/generateTrackInfoPage.js +++ b/src/content/dependencies/generateTrackInfoPage.js @@ -108,7 +108,7 @@ export default { track), flashesThatFeatureList: - relation('generateTrackInfoPageFeaturedByFlashesList', track), + relation('generateDividedFeaturedInFlashesList', track.featuredInFlashes, track), lyricsSection: relation('generateLyricsSection', track.lyrics), diff --git a/src/content/dependencies/listTracksInFlashesByAlbum.js b/src/content/dependencies/listTracksInFlashesByAlbum.js index db5472db..d1d659af 100644 --- a/src/content/dependencies/listTracksInFlashesByAlbum.js +++ b/src/content/dependencies/listTracksInFlashesByAlbum.js @@ -16,7 +16,7 @@ export default { const flashes = tracks.map(tracks => tracks.map(track => - track.featuredInFlashes)); + track.ownFeaturedInFlashes)); // Filter out tracks that aren't featured in any flashes. // This listing doesn't perform any sorting within albums. diff --git a/src/data/things/Track.js b/src/data/things/Track.js index 5cb6388a..36e3733d 100644 --- a/src/data/things/Track.js +++ b/src/data/things/Track.js @@ -5,7 +5,7 @@ import {colors} from '#cli'; import {input, V} from '#composite'; import find, {keyRefRegex} from '#find'; import {onlyItem} from '#sugar'; -import {sortByDate} from '#sort'; +import {sortByDate, sortFlashesChronologically} from '#sort'; import Thing from '#thing'; import {compareKebabCase} from '#wiki-data'; @@ -884,9 +884,44 @@ export class Track extends Thing { reverse: soupyReverse.input('tracksWhichSample'), }), - featuredInFlashes: reverseReferenceList({ + ownFeaturedInFlashes: reverseReferenceList({ reverse: soupyReverse.input('flashesWhichFeature'), }), + + featuredInFlashes: [ + { + dependencies: ['allReleases'], + compute: (continuation, {allReleases}) => continuation({ + ['#data']: + allReleases.flatMap(track => + track.ownFeaturedInFlashes.map(flash => ({ + flash, + track, + + // These properties are used for the upcoming sort. + act: flash.act, + date: flash.date, + }))), + }), + }, + + { + dependencies: ['#data'], + compute: (continuation, {'#data': data}) => continuation({ + ['#sortedData']: + sortFlashesChronologically(data), + }), + }, + + { + dependencies: ['#sortedData'], + compute: ({'#sortedData': sortedData}) => + sortedData.map(item => ({ + flash: item.flash, + as: item.track, + })), + }, + ], }); static [Thing.yamlDocumentSpec] = { diff --git a/src/data/things/WikiInfo.js b/src/data/things/WikiInfo.js index ffb18cd8..364ae517 100644 --- a/src/data/things/WikiInfo.js +++ b/src/data/things/WikiInfo.js @@ -1,6 +1,5 @@ import {input, V} from '#composite'; import Thing from '#thing'; -import {parseContributionPresets, parseWallpaperParts} from '#yaml'; import { isBoolean, @@ -10,9 +9,16 @@ import { isNumber, } from '#validators'; +import { + parseAnnotatedReferences, + parseContributionPresets, + parseWallpaperParts, +} from '#yaml'; + import {exitWithoutDependency, exposeConstant} from '#composite/control-flow'; import { + annotatedReferenceList, canonicalBase, color, contentString, @@ -30,7 +36,7 @@ export class WikiInfo extends Thing { static [Thing.wikiData] = 'wikiInfo'; static [Thing.oneInstancePerWiki] = true; - static [Thing.getPropertyDescriptors] = ({Group}) => ({ + static [Thing.getPropertyDescriptors] = ({FlashSide, Group}) => ({ // Update & expose name: name(V('Unnamed Wiki')), @@ -75,6 +81,15 @@ export class WikiInfo extends Thing { find: soupyFind.input('group'), }), + divideFlashListsBySides: annotatedReferenceList({ + class: input.value(FlashSide), + find: soupyFind.input('flashSide'), + + reference: input.value('side'), + annotation: input.value('label'), + thing: input.value('side'), + }), + contributionPresets: { flags: {update: true, expose: true}, update: {validate: isContributionPresetList}, @@ -147,6 +162,17 @@ export class WikiInfo extends Thing { 'Divide Track Lists By Groups': {property: 'divideTrackListsByGroups'}, + 'Divide Flash Lists By Sides': { + property: 'divideFlashListsBySides', + transform: value => + parseAnnotatedReferences(value, { + referenceField: 'Side', + referenceProperty: 'side', + annotationField: 'Label', + annotationProperty: 'label', + }), + }, + 'Contribution Presets': { property: 'contributionPresets', transform: parseContributionPresets, diff --git a/src/strings-default.yaml b/src/strings-default.yaml index 0b0df861..34d3cb07 100644 --- a/src/strings-default.yaml +++ b/src/strings-default.yaml @@ -339,10 +339,6 @@ releaseInfo: _: "Flashes that feature {TRACK}:" sticky: "Flashes that feature this track:" - item: - _: "{FLASH}" - asDifferentRelease: "{FLASH} (as {TRACK})" - referencesArtworks: "References {ARTWORKS}." referencedByArtworks: "Referenced by {ARTWORKS}." @@ -472,6 +468,13 @@ trackList: rerelease: >- {TRACK} (rerelease) +flashList: + underSide: "under {SIDE}:" + + item: + _: "{FLASH}" + asDifferentRelease: "{FLASH} (as {TRACK})" + # # misc: # |