diff options
Diffstat (limited to 'src/data/things')
-rw-r--r-- | src/data/things/album.js | 87 | ||||
-rw-r--r-- | src/data/things/art-tag.js | 21 | ||||
-rw-r--r-- | src/data/things/artist.js | 31 | ||||
-rw-r--r-- | src/data/things/flash.js | 47 | ||||
-rw-r--r-- | src/data/things/group.js | 47 | ||||
-rw-r--r-- | src/data/things/homepage-layout.js | 38 | ||||
-rw-r--r-- | src/data/things/news-entry.js | 21 | ||||
-rw-r--r-- | src/data/things/static-page.js | 28 | ||||
-rw-r--r-- | src/data/things/track.js | 3 | ||||
-rw-r--r-- | src/data/things/wiki-info.js | 21 |
10 files changed, 343 insertions, 1 deletions
diff --git a/src/data/things/album.js b/src/data/things/album.js index 9e6d28d9..9d4729e4 100644 --- a/src/data/things/album.js +++ b/src/data/things/album.js @@ -1,5 +1,11 @@ +export const DATA_ALBUM_DIRECTORY = 'album'; + +import * as path from 'node:path'; + import {input} from '#composite'; import find from '#find'; +import {traverse} from '#node-utils'; +import {empty} from '#sugar'; import Thing from '#thing'; import {isDate} from '#validators'; import {parseAdditionalFiles, parseContributors, parseDate, parseDimensions} @@ -283,6 +289,87 @@ export class Album extends Thing { 'Review Points': {ignore: true}, }, }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {headerAndEntries}, + thingConstructors: {Album, Track, TrackSectionHelper}, + }) => ({ + title: `Process album files`, + + files: dataPath => + traverse(path.join(dataPath, DATA_ALBUM_DIRECTORY), { + filterFile: name => path.extname(name) === '.yaml', + prefixPath: DATA_ALBUM_DIRECTORY, + }), + + documentMode: headerAndEntries, + headerDocumentThing: Album, + entryDocumentThing: document => + ('Section' in document + ? TrackSectionHelper + : Track), + + save(results) { + const albumData = []; + const trackData = []; + + for (const {header: album, entries} of results) { + // We can't mutate an array once it's set as a property value, + // so prepare the track sections that will show up in a track list + // all the way before actually applying them. (It's okay to mutate + // an individual section before applying it, since those are just + // generic objects; they aren't Things in and of themselves.) + const trackSections = []; + const ownTrackData = []; + + let currentTrackSection = { + name: `Default Track Section`, + isDefaultTrackSection: true, + tracks: [], + }; + + const albumRef = Thing.getReference(album); + + const closeCurrentTrackSection = () => { + if (!empty(currentTrackSection.tracks)) { + trackSections.push(currentTrackSection); + } + }; + + for (const entry of entries) { + if (entry instanceof TrackSectionHelper) { + closeCurrentTrackSection(); + + currentTrackSection = { + name: entry.name, + color: entry.color, + dateOriginallyReleased: entry.dateOriginallyReleased, + isDefaultTrackSection: false, + tracks: [], + }; + + continue; + } + + trackData.push(entry); + + entry.dataSourceAlbum = albumRef; + + ownTrackData.push(entry); + currentTrackSection.tracks.push(Thing.getReference(entry)); + } + + closeCurrentTrackSection(); + + albumData.push(album); + + album.trackSections = trackSections; + album.ownTrackData = ownTrackData; + } + + return {albumData, trackData}; + }, + }); } export class TrackSectionHelper extends Thing { diff --git a/src/data/things/art-tag.js b/src/data/things/art-tag.js index af6677f0..29cd2990 100644 --- a/src/data/things/art-tag.js +++ b/src/data/things/art-tag.js @@ -1,7 +1,9 @@ +export const ART_TAG_DATA_FILE = 'tags.yaml'; + import {input} from '#composite'; import Thing from '#thing'; import {isName} from '#validators'; -import {sortAlbumsTracksChronologically} from '#wiki-data'; +import {sortAlphabetically, sortAlbumsTracksChronologically} from '#wiki-data'; import {exposeUpdateValueOrContinue} from '#composite/control-flow'; @@ -73,4 +75,21 @@ export class ArtTag extends Thing { 'Is CW': {property: 'isContentWarning'}, }, }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {allInOne}, + thingConstructors: {ArtTag}, + }) => ({ + title: `Process art tags file`, + file: ART_TAG_DATA_FILE, + + documentMode: allInOne, + documentThing: ArtTag, + + save(artTagData) { + sortAlphabetically(artTagData); + + return {artTagData}; + }, + }); } diff --git a/src/data/things/artist.js b/src/data/things/artist.js index ab08f522..8f32afd7 100644 --- a/src/data/things/artist.js +++ b/src/data/things/artist.js @@ -1,3 +1,5 @@ +export const ARTIST_DATA_FILE = 'artists.yaml'; + import {input} from '#composite'; import find from '#find'; import {unique} from '#sugar'; @@ -257,4 +259,33 @@ export class Artist extends Thing { 'Review Points': {ignore: true}, }, }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {allInOne}, + thingConstructors: {Artist}, + }) => ({ + title: `Process artists file`, + file: ARTIST_DATA_FILE, + + documentMode: allInOne, + documentThing: Artist, + + save(results) { + const artistData = results; + + const artistAliasData = results.flatMap((artist) => { + const origRef = Thing.getReference(artist); + return artist.aliasNames?.map((name) => { + const alias = new Artist(); + alias.name = name; + alias.isAlias = true; + alias.aliasedArtist = origRef; + alias.artistData = artistData; + return alias; + }) ?? []; + }); + + return {artistData, artistAliasData}; + }, + }); } diff --git a/src/data/things/flash.js b/src/data/things/flash.js index 945d80dd..ad80cbf2 100644 --- a/src/data/things/flash.js +++ b/src/data/things/flash.js @@ -1,3 +1,5 @@ +export const FLASH_DATA_FILE = 'flashes.yaml'; + import {input} from '#composite'; import find from '#find'; import Thing from '#thing'; @@ -204,4 +206,49 @@ export class FlashAct extends Thing { 'Review Points': {ignore: true}, }, }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {allInOne}, + thingConstructors: {Flash, FlashAct}, + }) => ({ + title: `Process flashes file`, + file: FLASH_DATA_FILE, + + documentMode: allInOne, + documentThing: document => + ('Act' in document + ? FlashAct + : Flash), + + save(results) { + let flashAct; + let flashRefs = []; + + if (results[0] && !(results[0] instanceof FlashAct)) { + throw new Error(`Expected an act at top of flash data file`); + } + + for (const thing of results) { + if (thing instanceof FlashAct) { + if (flashAct) { + Object.assign(flashAct, {flashes: flashRefs}); + } + + flashAct = thing; + flashRefs = []; + } else { + flashRefs.push(Thing.getReference(thing)); + } + } + + if (flashAct) { + Object.assign(flashAct, {flashes: flashRefs}); + } + + const flashData = results.filter(x => x instanceof Flash); + const flashActData = results.filter(x => x instanceof FlashAct); + + return {flashData, flashActData}; + }, + }); } diff --git a/src/data/things/group.js b/src/data/things/group.js index adcd6ad1..a32cd64d 100644 --- a/src/data/things/group.js +++ b/src/data/things/group.js @@ -1,3 +1,5 @@ +export const GROUP_DATA_FILE = 'groups.yaml'; + import {input} from '#composite'; import find from '#find'; import Thing from '#thing'; @@ -97,6 +99,51 @@ export class Group extends Thing { 'Review Points': {ignore: true}, }, }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {allInOne}, + thingConstructors: {Group, GroupCategory}, + }) => ({ + title: `Process groups file`, + file: GROUP_DATA_FILE, + + documentMode: allInOne, + documentThing: document => + ('Category' in document + ? GroupCategory + : Group), + + save(results) { + let groupCategory; + let groupRefs = []; + + if (results[0] && !(results[0] instanceof GroupCategory)) { + throw new Error(`Expected a category at top of group data file`); + } + + for (const thing of results) { + if (thing instanceof GroupCategory) { + if (groupCategory) { + Object.assign(groupCategory, {groups: groupRefs}); + } + + groupCategory = thing; + groupRefs = []; + } else { + groupRefs.push(Thing.getReference(thing)); + } + } + + if (groupCategory) { + Object.assign(groupCategory, {groups: groupRefs}); + } + + const groupData = results.filter(x => x instanceof Group); + const groupCategoryData = results.filter(x => x instanceof GroupCategory); + + return {groupData, groupCategoryData}; + }, + }); } export class GroupCategory extends Thing { diff --git a/src/data/things/homepage-layout.js b/src/data/things/homepage-layout.js index 38fd5a7a..00d6aef5 100644 --- a/src/data/things/homepage-layout.js +++ b/src/data/things/homepage-layout.js @@ -1,3 +1,5 @@ +export const HOMEPAGE_LAYOUT_DATA_FILE = 'homepage.yaml'; + import {input} from '#composite'; import find from '#find'; import Thing from '#thing'; @@ -182,4 +184,40 @@ export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { 'Actions': {property: 'actionLinks'}, }, }); + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {headerAndEntries}, // Kludge, see below + thingConstructors: { + HomepageLayout, + HomepageLayoutAlbumsRow, + }, + }) => ({ + title: `Process homepage layout file`, + + // Kludge: This benefits from the same headerAndEntries style messaging as + // albums and tracks (for example), but that document mode is designed to + // support multiple files, and only one is actually getting processed here. + files: [HOMEPAGE_LAYOUT_DATA_FILE], + + documentMode: headerAndEntries, + headerDocumentThing: HomepageLayout, + entryDocumentThing: document => { + switch (document['Type']) { + case 'albums': + return HomepageLayoutAlbumsRow; + default: + throw new TypeError(`No processDocument function for row type ${document['Type']}!`); + } + }, + + save(results) { + if (!results[0]) { + return; + } + + const {header: homepageLayout, entries: rows} = results[0]; + Object.assign(homepageLayout, {rows}); + return {homepageLayout}; + }, + }); } diff --git a/src/data/things/news-entry.js b/src/data/things/news-entry.js index 5a022449..658453b0 100644 --- a/src/data/things/news-entry.js +++ b/src/data/things/news-entry.js @@ -1,4 +1,7 @@ +export const NEWS_DATA_FILE = 'news.yaml'; + import Thing from '#thing'; +import {sortChronologically} from '#wiki-data'; import {parseDate} from '#yaml'; import {contentString, directory, name, simpleDate} @@ -43,4 +46,22 @@ export class NewsEntry extends Thing { 'Content': {property: 'content'}, }, }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {allInOne}, + thingConstructors: {NewsEntry}, + }) => ({ + title: `Process news data file`, + file: NEWS_DATA_FILE, + + documentMode: allInOne, + documentThing: NewsEntry, + + save(newsData) { + sortChronologically(newsData); + newsData.reverse(); + + return {newsData}; + }, + }); } diff --git a/src/data/things/static-page.js b/src/data/things/static-page.js index 2da7312b..1e8cb7c6 100644 --- a/src/data/things/static-page.js +++ b/src/data/things/static-page.js @@ -1,5 +1,11 @@ +export const DATA_STATIC_PAGE_DIRECTORY = 'static-page'; + +import * as path from 'node:path'; + +import {traverse} from '#node-utils'; import Thing from '#thing'; import {isName} from '#validators'; +import {sortAlphabetically} from '#wiki-data'; import {contentString, directory, name, simpleString} from '#composite/wiki-properties'; @@ -42,4 +48,26 @@ export class StaticPage extends Thing { 'Review Points': {ignore: true}, }, }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {onePerFile}, + thingConstructors: {StaticPage}, + }) => ({ + title: `Process static page files`, + + files: dataPath => + traverse(path.join(dataPath, DATA_STATIC_PAGE_DIRECTORY), { + filterFile: name => path.extname(name) === '.yaml', + prefixPath: DATA_STATIC_PAGE_DIRECTORY, + }), + + documentMode: onePerFile, + documentThing: StaticPage, + + save(staticPageData) { + sortAlphabetically(staticPageData); + + return {staticPageData}; + }, + }); } diff --git a/src/data/things/track.js b/src/data/things/track.js index dd102683..d1a12aac 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -451,6 +451,9 @@ export class Track extends Thing { ], }; + // Track YAML loading is handled in album.js. + static [Thing.getYamlLoadingSpec] = null; + [inspect.custom](depth) { const parts = []; diff --git a/src/data/things/wiki-info.js b/src/data/things/wiki-info.js index fd6c239c..316bd3bb 100644 --- a/src/data/things/wiki-info.js +++ b/src/data/things/wiki-info.js @@ -1,3 +1,5 @@ +export const WIKI_INFO_FILE = 'wiki-info.yaml'; + import {input} from '#composite'; import find from '#find'; import Thing from '#thing'; @@ -86,4 +88,23 @@ export class WikiInfo extends Thing { 'Enable Group UI': {property: 'enableGroupUI'}, }, }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {oneDocumentTotal}, + thingConstructors: {WikiInfo}, + }) => ({ + title: `Process wiki info file`, + file: WIKI_INFO_FILE, + + documentMode: oneDocumentTotal, + documentThing: WikiInfo, + + save(wikiInfo) { + if (!wikiInfo) { + return; + } + + return {wikiInfo}; + }, + }); } |