diff options
| author | (quasar) nebula <qznebula@protonmail.com> | 2026-01-26 15:14:38 -0400 |
|---|---|---|
| committer | (quasar) nebula <qznebula@protonmail.com> | 2026-01-26 15:14:38 -0400 |
| commit | a074fd54107c51c4fcbfedbbf6df6eca539d19d3 (patch) | |
| tree | 4fec08106aa3054c1954c5fa4ade0fb880c5eeb3 /src/data/files | |
| parent | 796e4bc1452b918bbf50a2e802b308f6ac20f2c2 (diff) | |
data, yaml: split yaml loading specs into src/data/files
Diffstat (limited to 'src/data/files')
| -rw-r--r-- | src/data/files/album.js | 74 | ||||
| -rw-r--r-- | src/data/files/art-tag.js | 32 | ||||
| -rw-r--r-- | src/data/files/artist.js | 16 | ||||
| -rw-r--r-- | src/data/files/flash.js | 78 | ||||
| -rw-r--r-- | src/data/files/group.js | 45 | ||||
| -rw-r--r-- | src/data/files/homepage-layout.js | 87 | ||||
| -rw-r--r-- | src/data/files/index.js | 10 | ||||
| -rw-r--r-- | src/data/files/news.js | 16 | ||||
| -rw-r--r-- | src/data/files/sorting-rule.js | 13 | ||||
| -rw-r--r-- | src/data/files/static-page.js | 24 | ||||
| -rw-r--r-- | src/data/files/wiki-info.js | 10 |
11 files changed, 405 insertions, 0 deletions
diff --git a/src/data/files/album.js b/src/data/files/album.js new file mode 100644 index 00000000..84cda226 --- /dev/null +++ b/src/data/files/album.js @@ -0,0 +1,74 @@ +import * as path from 'node:path'; + +import {traverse} from '#node-utils'; +import {sortAlbumsTracksChronologically, sortChronologically} from '#sort'; +import {empty} from '#sugar'; + +export default ({ + documentModes: {headerAndEntries}, + thingConstructors: {Album, Track, TrackSection}, +}) => ({ + title: `Process album files`, + + files: dataPath => + traverse(path.join(dataPath, 'album'), { + filterFile: name => path.extname(name) === '.yaml', + prefixPath: 'album', + }), + + documentMode: headerAndEntries, + headerDocumentThing: Album, + entryDocumentThing: document => + ('Section' in document + ? TrackSection + : Track), + + connect({header: album, entries}) { + const trackSections = []; + + let currentTrackSection = new TrackSection(); + let currentTrackSectionTracks = []; + + Object.assign(currentTrackSection, { + name: `Default Track Section`, + isDefaultTrackSection: true, + }); + + const closeCurrentTrackSection = () => { + if ( + currentTrackSection.isDefaultTrackSection && + empty(currentTrackSectionTracks) + ) { + return; + } + + currentTrackSection.tracks = currentTrackSectionTracks; + currentTrackSection.album = album; + + trackSections.push(currentTrackSection); + }; + + for (const entry of entries) { + if (entry instanceof TrackSection) { + closeCurrentTrackSection(); + currentTrackSection = entry; + currentTrackSectionTracks = []; + continue; + } + + entry.album = album; + entry.trackSection = currentTrackSection; + + currentTrackSectionTracks.push(entry); + } + + closeCurrentTrackSection(); + + album.trackSections = trackSections; + }, + + sort({albumData, trackData}) { + sortChronologically(albumData); + sortAlbumsTracksChronologically(trackData); + }, +}); diff --git a/src/data/files/art-tag.js b/src/data/files/art-tag.js new file mode 100644 index 00000000..67a22ca7 --- /dev/null +++ b/src/data/files/art-tag.js @@ -0,0 +1,32 @@ +import {readFile} from 'node:fs/promises'; +import * as path from 'node:path'; + +import {traverse} from '#node-utils'; +import {sortAlphabetically} from '#sort'; + +export default ({ + documentModes: {allTogether}, + thingConstructors: {ArtTag}, +}) => ({ + title: `Process art tags file`, + + files: dataPath => + Promise.allSettled([ + readFile(path.join(dataPath, 'tags.yaml')) + .then(() => ['tags.yaml']), + + traverse(path.join(dataPath, 'art-tags'), { + filterFile: name => path.extname(name) === '.yaml', + prefixPath: 'art-tags', + }), + ]).then(results => results + .filter(({status}) => status === 'fulfilled') + .flatMap(({value}) => value)), + + documentMode: allTogether, + documentThing: ArtTag, + + sort({artTagData}) { + sortAlphabetically(artTagData); + }, +}); diff --git a/src/data/files/artist.js b/src/data/files/artist.js new file mode 100644 index 00000000..ef971171 --- /dev/null +++ b/src/data/files/artist.js @@ -0,0 +1,16 @@ +import {sortAlphabetically} from '#sort'; + +export default ({ + documentModes: {allInOne}, + thingConstructors: {Artist}, +}) => ({ + title: `Process artists file`, + file: 'artists.yaml', + + documentMode: allInOne, + documentThing: Artist, + + sort({artistData}) { + sortAlphabetically(artistData); + }, +}); diff --git a/src/data/files/flash.js b/src/data/files/flash.js new file mode 100644 index 00000000..3e4f750f --- /dev/null +++ b/src/data/files/flash.js @@ -0,0 +1,78 @@ +import {sortFlashesChronologically} from '#sort'; + +export default ({ + documentModes: {allInOne}, + thingConstructors: {Flash, FlashAct, FlashSide}, +}) => ({ + title: `Process flashes file`, + file: 'flashes.yaml', + + documentMode: allInOne, + documentThing: document => + ('Side' in document + ? FlashSide + : 'Act' in document + ? FlashAct + : Flash), + + connect(results) { + let thing, i; + + for (i = 0; thing = results[i]; i++) { + if (thing.isFlashSide) { + const side = thing; + const acts = []; + + for (i++; thing = results[i]; i++) { + if (thing.isFlashAct) { + const act = thing; + const flashes = []; + + for (i++; thing = results[i]; i++) { + if (thing.isFlash) { + const flash = thing; + + flash.act = act; + flashes.push(flash); + + continue; + } + + i--; + break; + } + + act.side = side; + act.flashes = flashes; + acts.push(act); + + continue; + } + + if (thing.isFlash) { + throw new Error(`Flashes must be under an act`); + } + + i--; + break; + } + + side.acts = acts; + + continue; + } + + if (thing.isFlashAct) { + throw new Error(`Acts must be under a side`); + } + + if (thing.isFlash) { + throw new Error(`Flashes must be under a side and act`); + } + } + }, + + sort({flashData}) { + sortFlashesChronologically(flashData); + }, +}); diff --git a/src/data/files/group.js b/src/data/files/group.js new file mode 100644 index 00000000..c10cbf98 --- /dev/null +++ b/src/data/files/group.js @@ -0,0 +1,45 @@ +import Thing from '#thing'; + +export default ({ + documentModes: {allInOne}, + thingConstructors: {Group, GroupCategory}, +}) => ({ + title: `Process groups file`, + file: 'groups.yaml', + + documentMode: allInOne, + documentThing: document => + ('Category' in document + ? GroupCategory + : Group), + + connect(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}); + } + }, + + // Groups aren't sorted at all, always preserving the order in the data + // file as-is. + sort: null, +}); diff --git a/src/data/files/homepage-layout.js b/src/data/files/homepage-layout.js new file mode 100644 index 00000000..646beff6 --- /dev/null +++ b/src/data/files/homepage-layout.js @@ -0,0 +1,87 @@ +import {empty} from '#sugar'; + +export default ({ + documentModes: {allInOne}, + thingConstructors: { + HomepageLayout, + HomepageLayoutActionsRow, + HomepageLayoutAlbumCarouselRow, + HomepageLayoutAlbumGridRow, + HomepageLayoutRow, + HomepageLayoutSection, + }, +}) => ({ + title: `Process homepage layout file`, + file: 'homepage.yaml', + + documentMode: allInOne, + documentThing: document => { + if (document['Homepage']) { + return HomepageLayout; + } + + if (document['Section']) { + return HomepageLayoutSection; + } + + if (document['Row']) { + switch (document['Row']) { + case 'actions': + return HomepageLayoutActionsRow; + case 'album carousel': + return HomepageLayoutAlbumCarouselRow; + case 'album grid': + return HomepageLayoutAlbumGridRow; + default: + throw new TypeError(`Unrecognized row type ${document['Row']}`); + } + } + + return null; + }, + + connect(results) { + if (!empty(results) && !(results[0] instanceof HomepageLayout)) { + throw new Error(`Expected 'Homepage' document at top of homepage layout file`); + } + + const homepageLayout = results[0]; + const sections = []; + + let currentSection = null; + let currentSectionRows = []; + + const closeCurrentSection = () => { + if (currentSection) { + for (const row of currentSectionRows) { + row.section = currentSection; + } + + currentSection.rows = currentSectionRows; + sections.push(currentSection); + + currentSection = null; + currentSectionRows = []; + } + }; + + for (const entry of results.slice(1)) { + if (entry instanceof HomepageLayout) { + throw new Error(`Expected only one 'Homepage' document in total`); + } else if (entry instanceof HomepageLayoutSection) { + closeCurrentSection(); + currentSection = entry; + } else if (entry instanceof HomepageLayoutRow) { + if (currentSection) { + currentSectionRows.push(entry); + } else { + throw new Error(`Expected a 'Section' document to add following rows into`); + } + } + } + + closeCurrentSection(); + + homepageLayout.sections = sections; + }, +}); diff --git a/src/data/files/index.js b/src/data/files/index.js new file mode 100644 index 00000000..f3efebad --- /dev/null +++ b/src/data/files/index.js @@ -0,0 +1,10 @@ +export {default as getAlbumLoadingSpec} from './album.js'; +export {default as getArtistLoadingSpec} from './artist.js'; +export {default as getArtTagLoadingSpec} from './art-tag.js'; +export {default as getFlashLoadingSpec} from './flash.js'; +export {default as getGroupLoadingSpec} from './group.js'; +export {default as getHomepageLayoutLoadingSpec} from './homepage-layout.js'; +export {default as getNewsLoadingSpec} from './news.js'; +export {default as getSortingRuleLoadingSpec} from './sorting-rule.js'; +export {default as getStaticPageLoadingSpec} from './static-page.js'; +export {default as getWikiInfoLoadingSpec} from './wiki-info.js'; diff --git a/src/data/files/news.js b/src/data/files/news.js new file mode 100644 index 00000000..5b4a3029 --- /dev/null +++ b/src/data/files/news.js @@ -0,0 +1,16 @@ +import {sortChronologically} from '#sort'; + +export default ({ + documentModes: {allInOne}, + thingConstructors: {NewsEntry}, +}) => ({ + title: `Process news data file`, + file: 'news.yaml', + + documentMode: allInOne, + documentThing: NewsEntry, + + sort({newsData}) { + sortChronologically(newsData, {latestFirst: true}); + }, +}); diff --git a/src/data/files/sorting-rule.js b/src/data/files/sorting-rule.js new file mode 100644 index 00000000..61e1df23 --- /dev/null +++ b/src/data/files/sorting-rule.js @@ -0,0 +1,13 @@ +export default ({ + documentModes: {allInOne}, + thingConstructors: {DocumentSortingRule}, +}) => ({ + title: `Process sorting rules file`, + file: 'sorting-rules.yaml', + + documentMode: allInOne, + documentThing: document => + (document['Sort Documents'] + ? DocumentSortingRule + : null), +}); diff --git a/src/data/files/static-page.js b/src/data/files/static-page.js new file mode 100644 index 00000000..c7622bc8 --- /dev/null +++ b/src/data/files/static-page.js @@ -0,0 +1,24 @@ +import * as path from 'node:path'; + +import {traverse} from '#node-utils'; +import {sortAlphabetically} from '#sort'; + +export default ({ + documentModes: {onePerFile}, + thingConstructors: {StaticPage}, +}) => ({ + title: `Process static page files`, + + files: dataPath => + traverse(path.join(dataPath, 'static-page'), { + filterFile: name => path.extname(name) === '.yaml', + prefixPath: 'static-page', + }), + + documentMode: onePerFile, + documentThing: StaticPage, + + sort({staticPageData}) { + sortAlphabetically(staticPageData); + }, +}); diff --git a/src/data/files/wiki-info.js b/src/data/files/wiki-info.js new file mode 100644 index 00000000..a466ab0b --- /dev/null +++ b/src/data/files/wiki-info.js @@ -0,0 +1,10 @@ +export default ({ + documentModes: {oneDocumentTotal}, + thingConstructors: {WikiInfo}, +}) => ({ + title: `Process wiki info file`, + file: 'wiki-info.yaml', + + documentMode: oneDocumentTotal, + documentThing: WikiInfo, +}); |