diff options
author | (quasar) nebula <qznebula@protonmail.com> | 2024-01-20 16:13:36 -0400 |
---|---|---|
committer | (quasar) nebula <qznebula@protonmail.com> | 2024-01-30 07:59:34 -0400 |
commit | 296a4961a951e44ea53509391ad225d1491197f9 (patch) | |
tree | 4bdedf0f85b7af8d3039bb46ccfd2f1f600db5ce /src/data/things | |
parent | ac277f23abe0d8432a94f72913f4421b0eebaa62 (diff) |
yaml, data: store document specs statically on Thing subclasses
Diffstat (limited to 'src/data/things')
-rw-r--r-- | src/data/things/album.js | 79 | ||||
-rw-r--r-- | src/data/things/art-tag.js | 11 | ||||
-rw-r--r-- | src/data/things/artist.js | 20 | ||||
-rw-r--r-- | src/data/things/flash.js | 43 | ||||
-rw-r--r-- | src/data/things/group.js | 20 | ||||
-rw-r--r-- | src/data/things/homepage-layout.js | 29 | ||||
-rw-r--r-- | src/data/things/news-entry.js | 13 | ||||
-rw-r--r-- | src/data/things/static-page.js | 14 | ||||
-rw-r--r-- | src/data/things/thing.js | 42 | ||||
-rw-r--r-- | src/data/things/track.js | 95 | ||||
-rw-r--r-- | src/data/things/wiki-info.js | 18 |
11 files changed, 376 insertions, 8 deletions
diff --git a/src/data/things/album.js b/src/data/things/album.js index e48ad41a..02d34544 100644 --- a/src/data/things/album.js +++ b/src/data/things/album.js @@ -25,10 +25,13 @@ import { wikiData, } from '#composite/wiki-properties'; +import {withTracks, withTrackSections} from '#composite/things/album'; + import { - withTracks, - withTrackSections, -} from '#composite/things/album'; + parseAdditionalFiles, + parseContributors, + parseDimensions, +} from '#yaml'; import Thing from './thing.js'; @@ -200,6 +203,64 @@ export class Album extends Thing { artTags: S.toRefs, commentatorArtists: S.toRefs, }); + + static [Thing.yamlDocumentSpec] = { + fieldTransformations: { + 'Artists': parseContributors, + 'Cover Artists': parseContributors, + 'Default Track Cover Artists': parseContributors, + 'Wallpaper Artists': parseContributors, + 'Banner Artists': parseContributors, + + 'Date': (value) => new Date(value), + 'Date Added': (value) => new Date(value), + 'Cover Art Date': (value) => new Date(value), + 'Default Track Cover Art Date': (value) => new Date(value), + + 'Banner Dimensions': parseDimensions, + + 'Additional Files': parseAdditionalFiles, + }, + + propertyFieldMapping: { + name: 'Album', + directory: 'Directory', + date: 'Date', + color: 'Color', + urls: 'URLs', + + hasTrackNumbers: 'Has Track Numbers', + isListedOnHomepage: 'Listed on Homepage', + isListedInGalleries: 'Listed in Galleries', + + coverArtDate: 'Cover Art Date', + trackArtDate: 'Default Track Cover Art Date', + dateAddedToWiki: 'Date Added', + + coverArtFileExtension: 'Cover Art File Extension', + trackCoverArtFileExtension: 'Track Art File Extension', + + wallpaperArtistContribs: 'Wallpaper Artists', + wallpaperStyle: 'Wallpaper Style', + wallpaperFileExtension: 'Wallpaper File Extension', + + bannerArtistContribs: 'Banner Artists', + bannerStyle: 'Banner Style', + bannerFileExtension: 'Banner File Extension', + bannerDimensions: 'Banner Dimensions', + + commentary: 'Commentary', + additionalFiles: 'Additional Files', + + artistContribs: 'Artists', + coverArtistContribs: 'Cover Artists', + trackCoverArtistContribs: 'Default Track Cover Artists', + groups: 'Groups', + artTags: 'Art Tags', + }, + + ignoredFields: ['Review Points'], + }; } export class TrackSectionHelper extends Thing { @@ -211,4 +272,16 @@ export class TrackSectionHelper extends Thing { dateOriginallyReleased: simpleDate(), isDefaultTrackGroup: flag(false), }) + + static [Thing.yamlDocumentSpec] = { + fieldTransformations: { + 'Date Originally Released': (value) => new Date(value), + }, + + propertyFieldMapping: { + name: 'Section', + color: 'Color', + dateOriginallyReleased: 'Date Originally Released', + }, + }; } diff --git a/src/data/things/art-tag.js b/src/data/things/art-tag.js index f9e5f0f3..c0b4a6d6 100644 --- a/src/data/things/art-tag.js +++ b/src/data/things/art-tag.js @@ -63,4 +63,15 @@ export class ArtTag extends Thing { }, }, }); + + static [Thing.yamlDocumentSpec] = { + propertyFieldMapping: { + name: 'Tag', + nameShort: 'Short Name', + directory: 'Directory', + + color: 'Color', + isContentWarning: 'Is CW', + }, + }; } diff --git a/src/data/things/artist.js b/src/data/things/artist.js index a58cebc4..42090557 100644 --- a/src/data/things/artist.js +++ b/src/data/things/artist.js @@ -16,9 +16,7 @@ import { wikiData, } from '#composite/wiki-properties'; -import { - withReverseContributionList, -} from '#composite/wiki-data'; +import {withReverseContributionList} from '#composite/wiki-data'; import Thing from './thing.js'; @@ -242,4 +240,20 @@ export class Artist extends Thing { flashesAsContributor: S.toRefs, }); + + static [Thing.yamlDocumentSpec] = { + propertyFieldMapping: { + name: 'Artist', + directory: 'Directory', + urls: 'URLs', + contextNotes: 'Context Notes', + + hasAvatar: 'Has Avatar', + avatarFileExtension: 'Avatar File Extension', + + aliasNames: 'Aliases', + }, + + ignoredFields: ['Dead URLs', 'Review Points'], + }; } diff --git a/src/data/things/flash.js b/src/data/things/flash.js index 85fe343e..d7e8bb46 100644 --- a/src/data/things/flash.js +++ b/src/data/things/flash.js @@ -28,6 +28,8 @@ import { import {withFlashAct} from '#composite/things/flash'; +import {parseContributors} from '#yaml'; + import Thing from './thing.js'; export class Flash extends Thing { @@ -133,6 +135,30 @@ export class Flash extends Thing { urls: S.id, color: S.id, }); + + static [Thing.yamlDocumentSpec] = { + fieldTransformations: { + 'Date': (value) => new Date(value), + + 'Contributors': parseContributors, + }, + + propertyFieldMapping: { + name: 'Flash', + directory: 'Directory', + page: 'Page', + color: 'Color', + urls: 'URLs', + + date: 'Date', + coverArtFileExtension: 'Cover Art File Extension', + + featuredTracks: 'Featured Tracks', + contributorContribs: 'Contributors', + }, + + ignoredFields: ['Review Points'], + }; } export class FlashAct extends Thing { @@ -170,5 +196,20 @@ export class FlashAct extends Thing { flashData: wikiData({ class: input.value(Flash), }), - }) + }); + + static [Thing.yamlDocumentSpec] = { + propertyFieldMapping: { + name: 'Act', + directory: 'Directory', + + color: 'Color', + listTerminology: 'List Terminology', + + jump: 'Jump', + jumpColor: 'Jump Color', + }, + + ignoredFields: ['Review Points'], + }; } diff --git a/src/data/things/group.js b/src/data/things/group.js index 38d169de..a9708fb4 100644 --- a/src/data/things/group.js +++ b/src/data/things/group.js @@ -85,6 +85,19 @@ export class Group extends Thing { }, }, }); + + static [Thing.yamlDocumentSpec] = { + propertyFieldMapping: { + name: 'Group', + directory: 'Directory', + description: 'Description', + urls: 'URLs', + + featuredAlbums: 'Featured Albums', + }, + + ignoredFields: ['Review Points'], + }; } export class GroupCategory extends Thing { @@ -111,4 +124,11 @@ export class GroupCategory extends Thing { class: input.value(Group), }), }); + + static [Thing.yamlDocumentSpec] = { + propertyFieldMapping: { + name: 'Category', + color: 'Color', + }, + }; } diff --git a/src/data/things/homepage-layout.js b/src/data/things/homepage-layout.js index dd6c1d9d..b4fb97db 100644 --- a/src/data/things/homepage-layout.js +++ b/src/data/things/homepage-layout.js @@ -45,7 +45,16 @@ export class HomepageLayout extends Thing { validate: validateArrayItems(validateInstanceOf(HomepageLayoutRow)), }, }, - }) + }); + + static [Thing.yamlDocumentSpec] = { + propertyFieldMapping: { + sidebarContent: 'Sidebar Content', + navbarLinks: 'Navbar Links', + }, + + ignoredFields: ['Homepage'], + }; } export class HomepageLayoutRow extends Thing { @@ -82,6 +91,14 @@ export class HomepageLayoutRow extends Thing { class: input.value(Group), }), }); + + static [Thing.yamlDocumentSpec] = { + propertyFieldMapping: { + name: 'Row', + color: 'Color', + type: 'Type', + }, + }; } export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { @@ -162,4 +179,14 @@ export class HomepageLayoutAlbumsRow extends HomepageLayoutRow { update: {validate: validateArrayItems(isString)}, }, }); + + static [Thing.yamlDocumentSpec] = Thing.extendDocumentSpec(HomepageLayoutRow, { + propertyFieldMapping: { + displayStyle: 'Display Style', + sourceGroup: 'Group', + countAlbumsFromGroup: 'Count', + sourceAlbums: 'Albums', + actionLinks: 'Actions', + }, + }); } diff --git a/src/data/things/news-entry.js b/src/data/things/news-entry.js index f220b270..06dad629 100644 --- a/src/data/things/news-entry.js +++ b/src/data/things/news-entry.js @@ -32,4 +32,17 @@ export class NewsEntry extends Thing { }, }, }); + + static [Thing.yamlDocumentSpec] = { + fieldTransformations: { + 'Date': (value) => new Date(value), + }, + + propertyFieldMapping: { + name: 'Name', + directory: 'Directory', + date: 'Date', + content: 'Content', + }, + }; } diff --git a/src/data/things/static-page.js b/src/data/things/static-page.js index d1cc5b26..00c0b09c 100644 --- a/src/data/things/static-page.js +++ b/src/data/things/static-page.js @@ -33,4 +33,18 @@ export class StaticPage extends Thing { stylesheet: simpleString(), script: simpleString(), }); + + static [Thing.yamlDocumentSpec] = { + propertyFieldMapping: { + name: 'Name', + nameShort: 'Short Name', + directory: 'Directory', + + stylesheet: 'Style', + script: 'Script', + content: 'Content', + }, + + ignoredFields: ['Review Points'], + }; } diff --git a/src/data/things/thing.js b/src/data/things/thing.js index def7e914..42971c04 100644 --- a/src/data/things/thing.js +++ b/src/data/things/thing.js @@ -14,6 +14,8 @@ export default class Thing extends CacheableObject { static getPropertyDescriptors = Symbol('Thing.getPropertyDescriptors'); static getSerializeDescriptors = Symbol('Thing.getSerializeDescriptors'); + static yamlDocumentSpec = Symbol.for('Thing.yamlDocumentSpec'); + // Default custom inspect function, which may be overridden by Thing // subclasses. This will be used when displaying aggregate errors and other // command-line logging - it's the place to provide information useful in @@ -38,4 +40,44 @@ export default class Thing extends CacheableObject { return `${thing.constructor[Thing.referenceType]}:${thing.directory}`; } + + static extendDocumentSpec(thingClass, subspec) { + const superspec = thingClass[Thing.yamlDocumentSpec]; + + const { + fieldTransformations, + propertyFieldMapping, + ignoredFields, + invalidFieldCombinations, + ...restOfSubspec + } = subspec; + + const newFields = + Object.values(subspec.propertyFieldMapping ?? {}); + + return { + ...superspec, + ...restOfSubspec, + + fieldTransformations: { + ...superspec.fieldTransformations, + ...fieldTransformations, + }, + + propertyFieldMapping: { + ...superspec.propertyFieldMapping, + ...propertyFieldMapping, + }, + + ignoredFields: + (superspec.ignoredFields ?? []) + .filter(field => newFields.includes(field)) + .concat(ignoredFields ?? []), + + invalidFieldCombinations: [ + ...superspec.invalidFieldCombinations ?? [], + ...invalidFieldCombinations ?? [], + ], + }; + } } diff --git a/src/data/things/track.js b/src/data/things/track.js index 375dd81d..3621510b 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -55,6 +55,13 @@ import { withPropertyFromAlbum, } from '#composite/things/track'; +import { + parseAdditionalFiles, + parseAdditionalNames, + parseContributors, + parseDuration, +} from '#yaml'; + import CacheableObject from './cacheable-object.js'; import Thing from './thing.js'; @@ -332,6 +339,94 @@ export class Track extends Thing { }), }); + static [Thing.yamlDocumentSpec] = { + fieldTransformations: { + 'Additional Names': parseAdditionalNames, + 'Duration': parseDuration, + + 'Date First Released': (value) => new Date(value), + 'Cover Art Date': (value) => new Date(value), + 'Has Cover Art': (value) => + (value === true ? false : + value === false ? true : + value), + + 'Artists': parseContributors, + 'Contributors': parseContributors, + 'Cover Artists': parseContributors, + + 'Additional Files': parseAdditionalFiles, + 'Sheet Music Files': parseAdditionalFiles, + 'MIDI Project Files': parseAdditionalFiles, + }, + + propertyFieldMapping: { + name: 'Track', + directory: 'Directory', + additionalNames: 'Additional Names', + duration: 'Duration', + color: 'Color', + urls: 'URLs', + + dateFirstReleased: 'Date First Released', + coverArtDate: 'Cover Art Date', + coverArtFileExtension: 'Cover Art File Extension', + disableUniqueCoverArt: 'Has Cover Art', // This gets transformed to flip true/false. + + alwaysReferenceByDirectory: 'Always Reference By Directory', + + lyrics: 'Lyrics', + commentary: 'Commentary', + additionalFiles: 'Additional Files', + sheetMusicFiles: 'Sheet Music Files', + midiProjectFiles: 'MIDI Project Files', + + originalReleaseTrack: 'Originally Released As', + referencedTracks: 'Referenced Tracks', + sampledTracks: 'Sampled Tracks', + artistContribs: 'Artists', + contributorContribs: 'Contributors', + coverArtistContribs: 'Cover Artists', + artTags: 'Art Tags', + }, + + ignoredFields: ['Review Points'], + + invalidFieldCombinations: [ + {message: `Re-releases inherit references from the original`, fields: [ + 'Originally Released As', + 'Referenced Tracks', + ]}, + + {message: `Re-releases inherit samples from the original`, fields: [ + 'Originally Released As', + 'Sampled Tracks', + ]}, + + {message: `Re-releases inherit artists from the original`, fields: [ + 'Originally Released As', + 'Artists', + ]}, + + {message: `Re-releases inherit contributors from the original`, fields: [ + 'Originally Released As', + 'Contributors', + ]}, + + { + message: ({'Has Cover Art': hasCoverArt}) => + (hasCoverArt + ? `"Has Cover Art: true" is inferred from cover artist credits` + : `Tracks without cover art must not have cover artist credits`), + + fields: [ + 'Has Cover Art', + 'Cover Artists', + ], + }, + ], + }; + [inspect.custom](depth) { const parts = []; diff --git a/src/data/things/wiki-info.js b/src/data/things/wiki-info.js index 112d454f..80793550 100644 --- a/src/data/things/wiki-info.js +++ b/src/data/things/wiki-info.js @@ -74,4 +74,22 @@ export class WikiInfo extends Thing { class: input.value(Group), }), }); + + static [Thing.yamlDocumentSpec] = { + propertyFieldMapping: { + name: 'Name', + nameShort: 'Short Name', + color: 'Color', + description: 'Description', + footerContent: 'Footer Content', + defaultLanguage: 'Default Language', + canonicalBase: 'Canonical Base', + divideTrackListsByGroups: 'Divide Track Lists By Groups', + enableFlashesAndGames: 'Enable Flashes & Games', + enableListings: 'Enable Listings', + enableNews: 'Enable News', + enableArtTagUI: 'Enable Art Tag UI', + enableGroupUI: 'Enable Group UI', + }, + }; } |