From 1f37e5d6b0c6fccc9c46aabd7bd402375131d452 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 26 Jan 2026 14:07:13 -0400 Subject: data: break up content.js, flash.js, sorting-rule.js --- src/data/things/flash/Flash.js | 246 +++++++++++++++++++++++++++++++++++++ src/data/things/flash/FlashAct.js | 74 +++++++++++ src/data/things/flash/FlashSide.js | 136 ++++++++++++++++++++ src/data/things/flash/index.js | 3 + 4 files changed, 459 insertions(+) create mode 100644 src/data/things/flash/Flash.js create mode 100644 src/data/things/flash/FlashAct.js create mode 100644 src/data/things/flash/FlashSide.js create mode 100644 src/data/things/flash/index.js (limited to 'src/data/things/flash') diff --git a/src/data/things/flash/Flash.js b/src/data/things/flash/Flash.js new file mode 100644 index 00000000..1f290b3f --- /dev/null +++ b/src/data/things/flash/Flash.js @@ -0,0 +1,246 @@ +import {input, V} from '#composite'; +import Thing from '#thing'; +import {anyOf, isColor, isDirectory, isNumber, isString} + from '#validators'; + +import { + parseArtwork, + parseAdditionalNames, + parseCommentary, + parseContributors, + parseCreditingSources, + parseDate, + parseDimensions, +} from '#yaml'; + +import {withPropertyFromObject} from '#composite/data'; + +import { + exposeConstant, + exposeDependency, + exposeUpdateValueOrContinue, +} from '#composite/control-flow'; + +import { + commentatorArtists, + constitutibleArtwork, + contributionList, + dimensions, + fileExtension, + name, + referenceList, + simpleDate, + soupyFind, + soupyReverse, + thing, + thingList, + urls, +} from '#composite/wiki-properties'; + +export class Flash extends Thing { + static [Thing.referenceType] = 'flash'; + static [Thing.wikiData] = 'flashData'; + + static [Thing.constitutibleProperties] = [ + 'coverArtwork', // from inline fields + ]; + + static [Thing.getPropertyDescriptors] = ({ + AdditionalName, + CommentaryEntry, + CreditingSourcesEntry, + FlashAct, + Track, + WikiInfo, + }) => ({ + // Update & expose + + act: thing(V(FlashAct)), + + name: name(V('Unnamed Flash')), + + directory: { + flags: {update: true, expose: true}, + update: {validate: isDirectory}, + + // Flashes expose directory differently from other Things! Their + // default directory is dependent on the page number (or ID), not + // the name. + expose: { + dependencies: ['page'], + transform(directory, {page}) { + if (directory === null && page === null) return null; + else if (directory === null) return page; + else return directory; + }, + }, + }, + + page: { + flags: {update: true, expose: true}, + update: {validate: anyOf(isString, isNumber)}, + + expose: { + transform: (value) => (value === null ? null : value.toString()), + }, + }, + + color: [ + exposeUpdateValueOrContinue({ + validate: input.value(isColor), + }), + + withPropertyFromObject('act', V('color')), + exposeDependency('#act.color'), + ], + + date: simpleDate(), + + coverArtFileExtension: fileExtension(V('jpg')), + + coverArtDimensions: dimensions(), + + coverArtwork: + constitutibleArtwork.fromYAMLFieldSpec + .call(this, 'Cover Artwork'), + + contributorContribs: contributionList({ + artistProperty: input.value('flashContributorContributions'), + }), + + featuredTracks: referenceList({ + class: input.value(Track), + find: soupyFind.input('track'), + }), + + urls: urls(), + + additionalNames: thingList(V(AdditionalName)), + + commentary: thingList(V(CommentaryEntry)), + creditingSources: thingList(V(CreditingSourcesEntry)), + + // Update only + + find: soupyFind(), + reverse: soupyReverse(), + + // used for withMatchingContributionPresets (indirectly by Contribution) + wikiInfo: thing(V(WikiInfo)), + + // Expose only + + isFlash: exposeConstant(V(true)), + + commentatorArtists: commentatorArtists(), + + side: [ + withPropertyFromObject('act', V('side')), + exposeDependency('#act.side'), + ], + }); + + static [Thing.getSerializeDescriptors] = ({ + serialize: S, + }) => ({ + name: S.id, + page: S.id, + directory: S.id, + date: S.id, + contributors: S.toContribRefs, + tracks: S.toRefs, + urls: S.id, + color: S.id, + }); + + static [Thing.findSpecs] = { + flash: { + referenceTypes: ['flash'], + bindTo: 'flashData', + }, + }; + + static [Thing.reverseSpecs] = { + flashesWhichFeature: { + bindTo: 'flashData', + + referencing: flash => [flash], + referenced: flash => flash.featuredTracks, + }, + + flashContributorContributionsBy: + soupyReverse.contributionsBy('flashData', 'contributorContribs'), + + flashesWithCommentaryBy: { + bindTo: 'flashData', + + referencing: flash => [flash], + referenced: flash => flash.commentatorArtists, + }, + }; + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Flash': {property: 'name'}, + 'Directory': {property: 'directory'}, + 'Page': {property: 'page'}, + 'Color': {property: 'color'}, + 'URLs': {property: 'urls'}, + + 'Date': { + property: 'date', + transform: parseDate, + }, + + 'Additional Names': { + property: 'additionalNames', + transform: parseAdditionalNames, + }, + + 'Cover Artwork': { + property: 'coverArtwork', + transform: + parseArtwork({ + single: true, + thingProperty: 'coverArtwork', + fileExtensionFromThingProperty: 'coverArtFileExtension', + dimensionsFromThingProperty: 'coverArtDimensions', + }), + }, + + 'Cover Art File Extension': {property: 'coverArtFileExtension'}, + + 'Cover Art Dimensions': { + property: 'coverArtDimensions', + transform: parseDimensions, + }, + + 'Featured Tracks': {property: 'featuredTracks'}, + + 'Contributors': { + property: 'contributorContribs', + transform: parseContributors, + }, + + 'Commentary': { + property: 'commentary', + transform: parseCommentary, + }, + + 'Crediting Sources': { + property: 'creditingSources', + transform: parseCreditingSources, + }, + + 'Review Points': {ignore: true}, + }, + }; + + getOwnArtworkPath(artwork) { + return [ + 'media.flashArt', + this.directory, + artwork.fileExtension, + ]; + } +} diff --git a/src/data/things/flash/FlashAct.js b/src/data/things/flash/FlashAct.js new file mode 100644 index 00000000..66d4ee1b --- /dev/null +++ b/src/data/things/flash/FlashAct.js @@ -0,0 +1,74 @@ + +import {input, V} from '#composite'; +import Thing from '#thing'; +import {isContentString} from '#validators'; + +import {withPropertyFromObject} from '#composite/data'; +import {exposeConstant, exposeDependency, exposeUpdateValueOrContinue} + from '#composite/control-flow'; +import {color, directory, name, soupyFind, soupyReverse, thing, thingList} + from '#composite/wiki-properties'; + +export class FlashAct extends Thing { + static [Thing.referenceType] = 'flash-act'; + static [Thing.friendlyName] = `Flash Act`; + static [Thing.wikiData] = 'flashActData'; + + static [Thing.getPropertyDescriptors] = ({Flash, FlashSide}) => ({ + // Update & expose + + side: thing(V(FlashSide)), + + name: name(V('Unnamed Flash Act')), + directory: directory(), + color: color(), + + listTerminology: [ + exposeUpdateValueOrContinue({ + validate: input.value(isContentString), + }), + + withPropertyFromObject('side', V('listTerminology')), + exposeDependency('#side.listTerminology'), + ], + + flashes: thingList(V(Flash)), + + // Update only + + find: soupyFind(), + reverse: soupyReverse(), + + // Expose only + + isFlashAct: exposeConstant(V(true)), + }); + + static [Thing.findSpecs] = { + flashAct: { + referenceTypes: ['flash-act'], + bindTo: 'flashActData', + }, + }; + + static [Thing.reverseSpecs] = { + flashActsWhoseFlashesInclude: { + bindTo: 'flashActData', + + referencing: flashAct => [flashAct], + referenced: flashAct => flashAct.flashes, + }, + }; + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Act': {property: 'name'}, + 'Directory': {property: 'directory'}, + + 'Color': {property: 'color'}, + 'List Terminology': {property: 'listTerminology'}, + + 'Review Points': {ignore: true}, + }, + }; +} diff --git a/src/data/things/flash/FlashSide.js b/src/data/things/flash/FlashSide.js new file mode 100644 index 00000000..72782bdd --- /dev/null +++ b/src/data/things/flash/FlashSide.js @@ -0,0 +1,136 @@ +const FLASH_DATA_FILE = 'flashes.yaml'; + +import {V} from '#composite'; +import {sortFlashesChronologically} from '#sort'; +import Thing from '#thing'; + +import {exposeConstant} from '#composite/control-flow'; +import {color, contentString, directory, name, soupyFind, thingList} + from '#composite/wiki-properties'; + +export class FlashSide extends Thing { + static [Thing.referenceType] = 'flash-side'; + static [Thing.friendlyName] = `Flash Side`; + static [Thing.wikiData] = 'flashSideData'; + + static [Thing.getPropertyDescriptors] = ({FlashAct}) => ({ + // Update & expose + + name: name(V('Unnamed Flash Side')), + directory: directory(), + color: color(), + listTerminology: contentString(), + + acts: thingList(V(FlashAct)), + + // Update only + + find: soupyFind(), + + // Expose only + + isFlashSide: exposeConstant(V(true)), + }); + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Side': {property: 'name'}, + 'Directory': {property: 'directory'}, + 'Color': {property: 'color'}, + 'List Terminology': {property: 'listTerminology'}, + }, + }; + + static [Thing.findSpecs] = { + flashSide: { + referenceTypes: ['flash-side'], + bindTo: 'flashSideData', + }, + }; + + static [Thing.reverseSpecs] = { + flashSidesWhoseActsInclude: { + bindTo: 'flashSideData', + + referencing: flashSide => [flashSide], + referenced: flashSide => flashSide.acts, + }, + }; + + static [Thing.getYamlLoadingSpec] = ({ + documentModes: {allInOne}, + thingConstructors: {Flash, FlashAct}, + }) => ({ + title: `Process flashes file`, + file: FLASH_DATA_FILE, + + 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/things/flash/index.js b/src/data/things/flash/index.js new file mode 100644 index 00000000..19b8cc34 --- /dev/null +++ b/src/data/things/flash/index.js @@ -0,0 +1,3 @@ +export * from './Flash.js'; +export * from './FlashAct.js'; +export * from './FlashSide.js'; -- cgit 1.3.0-6-gf8a5