diff options
Diffstat (limited to 'src/data/things')
| -rw-r--r-- | src/data/things/AdditionalFile.js | 56 | ||||
| -rw-r--r-- | src/data/things/Artist.js | 12 | ||||
| -rw-r--r-- | src/data/things/Language.js | 19 | ||||
| -rw-r--r-- | src/data/things/Track.js | 14 | ||||
| -rw-r--r-- | src/data/things/additional-file/AdditionalFile.js | 109 | ||||
| -rw-r--r-- | src/data/things/additional-file/MidiProjectFile.js | 28 | ||||
| -rw-r--r-- | src/data/things/additional-file/MiscellaneousAdditionalFile.js | 28 | ||||
| -rw-r--r-- | src/data/things/additional-file/SheetMusicFile.js | 28 | ||||
| -rw-r--r-- | src/data/things/additional-file/index.js | 5 | ||||
| -rw-r--r-- | src/data/things/album/Album.js | 21 | ||||
| -rw-r--r-- | src/data/things/index.js | 2 |
11 files changed, 246 insertions, 76 deletions
diff --git a/src/data/things/AdditionalFile.js b/src/data/things/AdditionalFile.js deleted file mode 100644 index e3f309a6..00000000 --- a/src/data/things/AdditionalFile.js +++ /dev/null @@ -1,56 +0,0 @@ -import {input} from '#composite'; -import Thing from '#thing'; -import {isString, validateArrayItems} from '#validators'; - -import {exposeConstant, exposeUpdateValueOrContinue} - from '#composite/control-flow'; -import {contentString, simpleString, thing} from '#composite/wiki-properties'; - -export class AdditionalFile extends Thing { - static [Thing.friendlyName] = `Additional File`; - - static [Thing.getPropertyDescriptors] = () => ({ - // Update & expose - - thing: thing(), - - title: simpleString(), - - description: contentString(), - - filenames: [ - exposeUpdateValueOrContinue({ - validate: input.value(validateArrayItems(isString)), - }), - - exposeConstant({ - value: input.value([]), - }), - ], - - // Expose only - - isAdditionalFile: [ - exposeConstant({ - value: input.value(true), - }), - ], - }); - - static [Thing.yamlDocumentSpec] = { - fields: { - 'Title': {property: 'title'}, - 'Description': {property: 'description'}, - 'Files': {property: 'filenames'}, - }, - }; - - get paths() { - if (!this.thing) return null; - if (!this.thing.getOwnAdditionalFilePath) return null; - - return ( - this.filenames.map(filename => - this.thing.getOwnAdditionalFilePath(this, filename))); - } -} diff --git a/src/data/things/Artist.js b/src/data/things/Artist.js index 64798527..89da3c88 100644 --- a/src/data/things/Artist.js +++ b/src/data/things/Artist.js @@ -273,6 +273,18 @@ export class Artist extends Thing { exposeDependency('#otherArtistContributions'), ], + miscellaneousAdditionalFileArtistContributions: reverseReferenceList({ + reverse: soupyReverse.input('miscellaneousAdditionalFileArtistContributionsBy'), + }), + + sheetMusicFileArtistContributions: reverseReferenceList({ + reverse: soupyReverse.input('sheetMusicFileArtistContributionsBy'), + }), + + midiProjectFileArtistContributions: reverseReferenceList({ + reverse: soupyReverse.input('midiProjectFileArtistContributionsBy'), + }), + totalDuration: [ withPropertyFromList('musicContributions', V('thing')), withPropertyFromList('#musicContributions.thing', V('isMainRelease')), diff --git a/src/data/things/Language.js b/src/data/things/Language.js index 2df58d19..5265d851 100644 --- a/src/data/things/Language.js +++ b/src/data/things/Language.js @@ -955,6 +955,7 @@ export class Language extends Thing { const countHelper = (stringKey, optionName = stringKey) => function(value, { unit = false, + unitOnly = false, blankIfZero = false, } = {}) { // Null or undefined value is blank content. @@ -967,22 +968,30 @@ const countHelper = (stringKey, optionName = stringKey) => return html.blank(); } - return this.formatString( - unit + const string = + (unitOnly + ? `count.${stringKey}.unitOnly.` + this.getUnitForm(value) + : unit ? `count.${stringKey}.withUnit.` + this.getUnitForm(value) - : `count.${stringKey}`, - {[optionName]: this.formatNumber(value)}); + : `count.${stringKey}`); + + const options = + (unitOnly + ? {} + : {[optionName]: this.formatNumber(value)}); + + return this.formatString(string, options); }; // TODO: These are hard-coded. Is there a better way? Object.assign(Language.prototype, { - countAdditionalFiles: countHelper('additionalFiles', 'files'), countAlbums: countHelper('albums'), countArtTags: countHelper('artTags', 'tags'), countArtworks: countHelper('artworks'), countCommentaryEntries: countHelper('commentaryEntries', 'entries'), countContributions: countHelper('contributions'), countDays: countHelper('days'), + countFiles: countHelper('files'), countFlashes: countHelper('flashes'), countMonths: countHelper('months'), countTimesFeatured: countHelper('timesFeatured'), diff --git a/src/data/things/Track.js b/src/data/things/Track.js index 8752b2bb..c47729e9 100644 --- a/src/data/things/Track.js +++ b/src/data/things/Track.js @@ -37,8 +37,10 @@ import { parseDimensions, parseDuration, parseLyrics, + parseMidiProjectFiles, parseMusicVideos, parseReferencingSources, + parseSheetMusicFiles, parseURLs, } from '#yaml'; @@ -1123,12 +1125,12 @@ export class Track extends Thing { 'Sheet Music Files': { property: 'sheetMusicFiles', - transform: parseAdditionalFiles, + transform: parseSheetMusicFiles, }, 'MIDI Project Files': { property: 'midiProjectFiles', - transform: parseAdditionalFiles, + transform: parseMidiProjectFiles, }, // Content entries @@ -1369,14 +1371,10 @@ export class Track extends Thing { }, }; - getOwnAdditionalFilePath(_file, filename) { + getOwnAdditionalFilePath(file, filename) { if (!this.album) return null; - return [ - 'media.albumAdditionalFile', - this.album.directory, - filename, - ]; + return this.album.getOwnAdditionalFilePath(file, filename); } getOwnArtworkPath(artwork) { diff --git a/src/data/things/additional-file/AdditionalFile.js b/src/data/things/additional-file/AdditionalFile.js new file mode 100644 index 00000000..d137c741 --- /dev/null +++ b/src/data/things/additional-file/AdditionalFile.js @@ -0,0 +1,109 @@ +import {inspect} from 'node:util'; + +import {colors} from '#cli'; +import {input, V} from '#composite'; +import Thing from '#thing'; +import {isString, validateArrayItems} from '#validators'; +import {parseContributors} from '#yaml'; + +import {exposeConstant, exposeUpdateValueOrContinue} + from '#composite/control-flow'; +import {contributionList, contentString, simpleString, soupyFind, thing} + from '#composite/wiki-properties'; + +export class AdditionalFile extends Thing { + static [Thing.friendlyName] = `Additional File`; + + static [Thing.getPropertyDescriptors] = () => ({ + // Update & expose + + thing: thing(), + + title: simpleString(), + + description: contentString(), + + folder: simpleString(), + + filenames: [ + exposeUpdateValueOrContinue({ + validate: input.value(validateArrayItems(isString)), + }), + + exposeConstant(V([])), + ], + + artistContribs: contributionList({ + // Subclasses override with the relevant artistProperty. + artistProperty: input.value(null), + }), + + // Update only + + find: soupyFind(), + + // Expose only + + isAdditionalFile: exposeConstant(V(true)), + + // The date property is generally expected by contributions. + // Additional files don't actually support dates, but provide a null + // value for convenience. + date: { + flags: {expose: true}, + expose: {compute: () => null}, + }, + }); + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Title': {property: 'title'}, + 'Description': {property: 'description'}, + + 'Artists': { + property: 'artistContribs', + transform: parseContributors, + }, + + 'Folder': {property: 'folder'}, + 'Files': {property: 'filenames'}, + }, + }; + + get paths() { + if (!this.thing) return null; + if (!this.thing.getOwnAdditionalFilePath) return null; + + return ( + this.filenames.map(filename => + this.thing.getOwnAdditionalFilePath(this, filename))); + } + + [inspect.custom](depth, options, inspect) { + const parts = []; + + parts.push(this.constructor.name); + + if (this.title) { + parts.push(` ${colors.green(`"${this.title}"`)}`); + } + + if (this.thing) { + if (depth >= 0) { + const newOptions = { + ...options, + depth: + (options.depth === null + ? null + : options.depth - 1), + }; + + parts.push(` for ${inspect(this.thing, newOptions)}`); + } else { + parts.push(` for ${colors.blue(Thing.inspectReference(this.thing))}`); + } + } + + return parts.join(''); + } +} diff --git a/src/data/things/additional-file/MidiProjectFile.js b/src/data/things/additional-file/MidiProjectFile.js new file mode 100644 index 00000000..8e7c19ca --- /dev/null +++ b/src/data/things/additional-file/MidiProjectFile.js @@ -0,0 +1,28 @@ +import {input, V} from '#composite'; +import Thing from '#thing'; + +import {exposeConstant} from '#composite/control-flow'; +import {contributionList, soupyReverse} from '#composite/wiki-properties'; + +import {AdditionalFile} from './AdditionalFile.js'; + +export class MidiProjectFile extends AdditionalFile { + static [Thing.wikiData] = 'midiProjectFileData'; + + static [Thing.getPropertyDescriptors] = () => ({ + // Update & expose + + artistContribs: contributionList({ + artistProperty: input.value('midiProjectFileArtistContributions'), + }), + + // Expose only + + isMidiProjectFile: exposeConstant(V(true)), + }); + + static [Thing.reverseSpecs] = { + midiProjectFileArtistContributionsBy: + soupyReverse.contributionsBy('midiProjectFileData', 'artistContribs'), + }; +} diff --git a/src/data/things/additional-file/MiscellaneousAdditionalFile.js b/src/data/things/additional-file/MiscellaneousAdditionalFile.js new file mode 100644 index 00000000..0110f830 --- /dev/null +++ b/src/data/things/additional-file/MiscellaneousAdditionalFile.js @@ -0,0 +1,28 @@ +import {input, V} from '#composite'; +import Thing from '#thing'; + +import {exposeConstant} from '#composite/control-flow'; +import {contributionList, soupyReverse} from '#composite/wiki-properties'; + +import {AdditionalFile} from './AdditionalFile.js'; + +export class MiscellaneousAdditionalFile extends AdditionalFile { + static [Thing.wikiData] = 'miscellaneousAdditionalFileData'; + + static [Thing.getPropertyDescriptors] = () => ({ + // Update & expose + + artistContribs: contributionList({ + artistProperty: input.value('miscellaneousAdditionalFileArtistContributions'), + }), + + // Expose only + + isMiscellaneousAdditionalFile: exposeConstant(V(true)), + }); + + static [Thing.reverseSpecs] = { + miscellaneousAdditionalFileArtistContributionsBy: + soupyReverse.contributionsBy('miscellaneousAdditionalFileData', 'artistContribs'), + }; +} diff --git a/src/data/things/additional-file/SheetMusicFile.js b/src/data/things/additional-file/SheetMusicFile.js new file mode 100644 index 00000000..c06cde7f --- /dev/null +++ b/src/data/things/additional-file/SheetMusicFile.js @@ -0,0 +1,28 @@ +import {input, V} from '#composite'; +import Thing from '#thing'; + +import {exposeConstant} from '#composite/control-flow'; +import {contributionList, soupyReverse} from '#composite/wiki-properties'; + +import {AdditionalFile} from './AdditionalFile.js'; + +export class SheetMusicFile extends AdditionalFile { + static [Thing.wikiData] = 'sheetMusicFileData'; + + static [Thing.getPropertyDescriptors] = () => ({ + // Update & expose + + artistContribs: contributionList({ + artistProperty: input.value('sheetMusicFileArtistContributions'), + }), + + // Expose only + + isSheetMusicFile: exposeConstant(V(true)), + }); + + static [Thing.reverseSpecs] = { + sheetMusicFileArtistContributionsBy: + soupyReverse.contributionsBy('sheetMusicFileData', 'artistContribs'), + }; +} diff --git a/src/data/things/additional-file/index.js b/src/data/things/additional-file/index.js new file mode 100644 index 00000000..d8de7455 --- /dev/null +++ b/src/data/things/additional-file/index.js @@ -0,0 +1,5 @@ +export * from './AdditionalFile.js'; + +export * from './MidiProjectFile.js'; +export * from './MiscellaneousAdditionalFile.js'; +export * from './SheetMusicFile.js' diff --git a/src/data/things/album/Album.js b/src/data/things/album/Album.js index f07d552c..201aaf4e 100644 --- a/src/data/things/album/Album.js +++ b/src/data/things/album/Album.js @@ -852,12 +852,21 @@ export class Album extends Thing { ], }; - getOwnAdditionalFilePath(_file, filename) { - return [ - 'media.albumAdditionalFile', - this.directory, - filename, - ]; + getOwnAdditionalFilePath(file, filename) { + if (file.folder) { + return [ + 'media.albumAdditionalFileInFolder', + this.directory, + file.folder, + filename, + ]; + } else { + return [ + 'media.albumAdditionalFile', + this.directory, + filename, + ]; + } } getOwnArtworkPath(artwork) { diff --git a/src/data/things/index.js b/src/data/things/index.js index 3773864b..8cd21e9d 100644 --- a/src/data/things/index.js +++ b/src/data/things/index.js @@ -1,5 +1,6 @@ // Not actually the entry point for #things - that's init.js in this folder. +export * from './additional-file/index.js'; export * from './album/index.js'; export * from './content/index.js'; export * from './contrib/index.js'; @@ -8,7 +9,6 @@ export * from './group/index.js'; export * from './homepage-layout/index.js'; export * from './sorting-rule/index.js'; -export * from './AdditionalFile.js'; export * from './AdditionalName.js'; export * from './ArtTag.js'; export * from './Artist.js'; |