diff options
Diffstat (limited to 'src/data')
| -rw-r--r-- | src/data/checks.js | 3 | ||||
| -rw-r--r-- | src/data/thing.js | 8 | ||||
| -rw-r--r-- | src/data/things/artist.js | 61 | ||||
| -rw-r--r-- | src/data/things/language.js | 10 | ||||
| -rw-r--r-- | src/data/things/track.js | 23 | ||||
| -rw-r--r-- | src/data/yaml.js | 24 |
6 files changed, 81 insertions, 48 deletions
diff --git a/src/data/checks.js b/src/data/checks.js index e68b2ed0..fd2c4931 100644 --- a/src/data/checks.js +++ b/src/data/checks.js @@ -60,7 +60,7 @@ export function reportDirectoryErrors(wikiData, { : [thing.directory]); for (const directory of directories) { - if (directory === null || directory === undefined) { + if (directory === '' || directory === null || directory === undefined) { missingDirectoryThings.add(thing); continue; } @@ -297,6 +297,7 @@ export function filterReferenceErrors(wikiData, { artistContribs: '_contrib', contributorContribs: '_contrib', coverArtistContribs: '_contrib', + previousProductionTracks: '_trackMainReleasesOnly', referencedTracks: '_trackMainReleasesOnly', sampledTracks: '_trackMainReleasesOnly', artTags: '_artTag', diff --git a/src/data/thing.js b/src/data/thing.js index f719224d..4fbad5f5 100644 --- a/src/data/thing.js +++ b/src/data/thing.js @@ -84,7 +84,13 @@ export default class Thing extends CacheableObject { } if (!thing.directory) { - throw TypeError(`Passed ${thing.constructor.name} is missing its directory`); + if (thing.name) { + throw TypeError( + `Passed ${thing.constructor.name} (named ${inspect(thing.name)}) ` + + `is missing its directory`); + } else { + throw TypeError(`Passed ${thing.constructor.name} is missing its directory`); + } } return `${thing.constructor[Thing.referenceType]}:${thing.directory}`; diff --git a/src/data/things/artist.js b/src/data/things/artist.js index 2905d893..24c99698 100644 --- a/src/data/things/artist.js +++ b/src/data/things/artist.js @@ -7,9 +7,9 @@ import {colors} from '#cli'; import {input} from '#composite'; import {stitchArrays} from '#sugar'; import Thing from '#thing'; -import {isName, validateArrayItems} from '#validators'; +import {validateArrayItems} from '#validators'; import {getKebabCase} from '#wiki-data'; -import {parseArtwork} from '#yaml'; +import {parseArtistAliases, parseArtwork} from '#yaml'; import { sortAlbumsTracksChronologically, @@ -32,6 +32,8 @@ import { singleReference, soupyFind, soupyReverse, + thing, + thingList, urls, } from '#composite/wiki-properties'; @@ -63,17 +65,14 @@ export class Artist extends Thing { .call(this, 'Avatar Artwork'), ], - aliasNames: { - flags: {update: true, expose: true}, - update: {validate: validateArrayItems(isName)}, - expose: {transform: (names) => names ?? []}, - }, - isAlias: flag(), - aliasedArtist: singleReference({ + artistAliases: thingList({ + class: input.value(Artist), + }), + + aliasedArtist: thing({ class: input.value(Artist), - find: soupyFind.input('artist'), }), // Update only @@ -251,8 +250,6 @@ export class Artist extends Thing { hasAvatar: S.id, avatarFileExtension: S.id, - aliasNames: S.id, - tracksAsCommentator: S.toRefs, albumsAsCommentator: S.toRefs, }); @@ -283,17 +280,9 @@ export class Artist extends Thing { // in the original's alias list. This is honestly a bit awkward, but it // avoids artist aliases conflicting with each other when checking for // duplicate directories. - for (const aliasName of originalArtist.aliasNames) { - // These are trouble. We should be accessing aliases' directories - // directly, but artists currently don't expose a reverse reference - // list for aliases. (This is pending a cleanup of "reverse reference" - // behavior in general.) It doesn't actually cause problems *here* - // because alias directories are computed from their names 100% of the - // time, but that *is* an assumption this code makes. - if (aliasName === artist.name) continue; - if (artist.directory === getKebabCase(aliasName)) { - return []; - } + for (const alias of originalArtist.artistAliases) { + if (alias === artist) break; + if (alias.directory === artist.directory) return []; } // And, aliases never return just a blank string. This part is pretty @@ -333,7 +322,10 @@ export class Artist extends Thing { 'Has Avatar': {property: 'hasAvatar'}, 'Avatar File Extension': {property: 'avatarFileExtension'}, - 'Aliases': {property: 'aliasNames'}, + 'Aliases': { + property: 'artistAliases', + transform: parseArtistAliases, + }, 'Dead URLs': {ignore: true}, @@ -353,26 +345,7 @@ export class Artist extends Thing { save(results) { const artists = results; - - const artistRefs = - artists.map(artist => Thing.getReference(artist)); - - const artistAliasNames = - artists.map(artist => artist.aliasNames); - - const artistAliases = - stitchArrays({ - originalArtistRef: artistRefs, - aliasNames: artistAliasNames, - }).flatMap(({originalArtistRef, aliasNames}) => - aliasNames.map(name => { - const alias = new Artist(); - alias.name = name; - alias.isAlias = true; - alias.aliasedArtist = originalArtistRef; - return alias; - })); - + const artistAliases = artists.flatMap(artist => artist.artistAliases); const artistData = [...artists, ...artistAliases]; const artworkData = diff --git a/src/data/things/language.js b/src/data/things/language.js index 91774761..43f69f3d 100644 --- a/src/data/things/language.js +++ b/src/data/things/language.js @@ -354,13 +354,19 @@ export class Language extends Thing { partInProgress += template.slice(lastIndex, match.index); - for (const insertionItem of html.smush(insertion).content) { + const insertionItems = html.smush(insertion).content; + if (insertionItems.length === 1 && typeof insertionItems[0] !== 'string') { + // Push the insertion exactly as it is, rather than manipulating. + if (partInProgress) outputParts.push(partInProgress); + outputParts.push(insertion); + partInProgress = ''; + } else for (const insertionItem of insertionItems) { if (typeof insertionItem === 'string') { // Join consecutive strings together. partInProgress += insertionItem; } else { // Push the string part in progress, then the insertion as-is. - outputParts.push(partInProgress); + if (partInProgress) outputParts.push(partInProgress); outputParts.push(insertionItem); partInProgress = ''; } diff --git a/src/data/things/track.js b/src/data/things/track.js index 93193b6a..64790a61 100644 --- a/src/data/things/track.js +++ b/src/data/things/track.js @@ -393,6 +393,17 @@ export class Track extends Thing { // > Update & expose - Referenced tracks + previousProductionTracks: [ + inheritFromMainRelease({ + notFoundValue: input.value([]), + }), + + referenceList({ + class: input.value(Track), + find: soupyFind.input('trackMainReleasesOnly'), + }), + ], + referencedTracks: [ inheritFromMainRelease({ notFoundValue: input.value([]), @@ -563,6 +574,10 @@ export class Track extends Thing { }), ], + followingProductionTracks: reverseReferenceList({ + reverse: soupyReverse.input('tracksWhichAreFollowingProductionsOf'), + }), + referencedByTracks: reverseReferenceList({ reverse: soupyReverse.input('tracksWhichReference'), }), @@ -701,6 +716,7 @@ export class Track extends Thing { // Referenced tracks + 'Previous Productions': {property: 'previousProductionTracks'}, 'Referenced Tracks': {property: 'referencedTracks'}, 'Sampled Tracks': {property: 'sampledTracks'}, @@ -912,6 +928,13 @@ export class Track extends Thing { referencing: track => track.isSecondaryRelease ? [track] : [], referenced: track => [track.mainReleaseTrack], }, + + tracksWhichAreFollowingProductionsOf: { + bindTo: 'trackData', + + referencing: track => track, + referenced: track => track.previousProductionTracks, + }, }; // Track YAML loading is handled in album.js. diff --git a/src/data/yaml.js b/src/data/yaml.js index 46cb4eda..13dfd24d 100644 --- a/src/data/yaml.js +++ b/src/data/yaml.js @@ -982,6 +982,30 @@ export function parseLyrics(value, {subdoc, LyricsEntry}) { return parseContentEntries(LyricsEntry, value, {subdoc}); } +export function parseArtistAliases(value, {subdoc, Artist}) { + return parseArrayEntries(value, item => { + const config = { + bindInto: 'aliasedArtist', + provide: {isAlias: true}, + }; + + if (typeof item === 'string') { + return subdoc(Artist, {'Artist': item}, config); + } else if (typeof item === 'object' && !Array.isArray(item)) { + if (item['Name']) { + const clone = {...item}; + clone['Artist'] = item['Name']; + delete clone['Name']; + return subdoc(Artist, clone, config); + } else { + return subdoc(Artist, item, config); + } + } else { + return item; + } + }); +} + // documentModes: Symbols indicating sets of behavior for loading and processing // data files. export const documentModes = { |