diff options
Diffstat (limited to 'src/data')
-rw-r--r-- | src/data/composite/control-flow/raiseOutputWithoutDependency.js | 2 | ||||
-rw-r--r-- | src/data/composite/control-flow/raiseOutputWithoutUpdateValue.js | 2 | ||||
-rw-r--r-- | src/data/composite/things/art-tag/index.js | 2 | ||||
-rw-r--r-- | src/data/composite/things/art-tag/withAllDescendantArtTags.js | 45 | ||||
-rw-r--r-- | src/data/composite/things/art-tag/withAncestorArtTagBaobabTree.js | 46 | ||||
-rw-r--r-- | src/data/things/art-tag.js | 66 | ||||
-rw-r--r-- | src/data/things/language.js | 67 | ||||
-rw-r--r-- | src/data/yaml.js | 10 |
8 files changed, 212 insertions, 28 deletions
diff --git a/src/data/composite/control-flow/raiseOutputWithoutDependency.js b/src/data/composite/control-flow/raiseOutputWithoutDependency.js index 03d8036a..3d04f8a9 100644 --- a/src/data/composite/control-flow/raiseOutputWithoutDependency.js +++ b/src/data/composite/control-flow/raiseOutputWithoutDependency.js @@ -17,7 +17,7 @@ export default templateCompositeFrom({ outputs: ({ [input.staticValue('output')]: output, - }) => Object.keys(output), + }) => Object.keys(output ?? {}), steps: () => [ withResultOfAvailabilityCheck({ diff --git a/src/data/composite/control-flow/raiseOutputWithoutUpdateValue.js b/src/data/composite/control-flow/raiseOutputWithoutUpdateValue.js index 3c39f5ba..ffa83a94 100644 --- a/src/data/composite/control-flow/raiseOutputWithoutUpdateValue.js +++ b/src/data/composite/control-flow/raiseOutputWithoutUpdateValue.js @@ -16,7 +16,7 @@ export default templateCompositeFrom({ outputs: ({ [input.staticValue('output')]: output, - }) => Object.keys(output), + }) => Object.keys(output ?? {}), steps: () => [ withResultOfAvailabilityCheck({ diff --git a/src/data/composite/things/art-tag/index.js b/src/data/composite/things/art-tag/index.js new file mode 100644 index 00000000..bbd38293 --- /dev/null +++ b/src/data/composite/things/art-tag/index.js @@ -0,0 +1,2 @@ +export {default as withAllDescendantArtTags} from './withAllDescendantArtTags.js'; +export {default as withAncestorArtTagBaobabTree} from './withAncestorArtTagBaobabTree.js'; diff --git a/src/data/composite/things/art-tag/withAllDescendantArtTags.js b/src/data/composite/things/art-tag/withAllDescendantArtTags.js new file mode 100644 index 00000000..c643cf23 --- /dev/null +++ b/src/data/composite/things/art-tag/withAllDescendantArtTags.js @@ -0,0 +1,45 @@ +// Gets all the art tags which descend from this one - that means its own direct +// descendants, but also all the direct and indirect desceands of each of those! +// The results aren't specially sorted, but they won't contain any duplicates +// (for example if two descendant tags both route deeper to end up including +// some of the same tags). + +import {input, templateCompositeFrom} from '#composite'; +import find from '#find'; +import {unique} from '#sugar'; + +import {raiseOutputWithoutDependency} from '#composite/control-flow'; +import {withResolvedReferenceList} from '#composite/wiki-data'; + +export default templateCompositeFrom({ + annotation: `withAllDescendantArtTags`, + + outputs: ['#allDescendantArtTags'], + + steps: () => [ + raiseOutputWithoutDependency({ + dependency: 'directDescendantArtTags', + mode: input.value('empty'), + output: input.value({'#allDescendantArtTags': []}) + }), + + withResolvedReferenceList({ + list: 'directDescendantArtTags', + data: 'artTagData', + find: input.value(find.artTag), + }), + + { + dependencies: ['#resolvedReferenceList'], + compute: (continuation, { + ['#resolvedReferenceList']: directDescendantArtTags, + }) => continuation({ + ['#allDescendantArtTags']: + unique([ + ...directDescendantArtTags, + ...directDescendantArtTags.flatMap(artTag => artTag.allDescendantArtTags), + ]), + }), + }, + ], +}) diff --git a/src/data/composite/things/art-tag/withAncestorArtTagBaobabTree.js b/src/data/composite/things/art-tag/withAncestorArtTagBaobabTree.js new file mode 100644 index 00000000..d5caa99e --- /dev/null +++ b/src/data/composite/things/art-tag/withAncestorArtTagBaobabTree.js @@ -0,0 +1,46 @@ +// Gets all the art tags which are ancestors of this one as a "baobab tree" - +// what you'd typically think of as roots are all up in the air! Since this +// really is backwards from the way that the art tag tree is written in data, +// chances are pretty good that there will be many of the exact same "leaf" +// nodes - art tags which don't themselves have any ancestors. In the actual +// data structure, each node is a Map, with keys for each ancestor and values +// for each ancestor's own baobab (thus a branching structure, just like normal +// trees in this regard). + +import {input, templateCompositeFrom} from '#composite'; + +import {raiseOutputWithoutDependency} from '#composite/control-flow'; +import {withReverseReferenceList} from '#composite/wiki-data'; + +export default templateCompositeFrom({ + annotation: `withAncestorArtTagBaobabTree`, + + outputs: ['#ancestorArtTagBaobabTree'], + + steps: () => [ + withReverseReferenceList({ + data: 'artTagData', + list: input.value('directDescendantArtTags'), + }).outputs({ + ['#reverseReferenceList']: '#directAncestorArtTags', + }), + + raiseOutputWithoutDependency({ + dependency: '#directAncestorArtTags', + mode: input.value('empty'), + output: input.value({'#ancestorArtTagBaobabTree': {}}) + }), + + { + dependencies: ['#directAncestorArtTags'], + compute: (continuation, { + ['#directAncestorArtTags']: directAncestorArtTags, + }) => continuation({ + ['#ancestorArtTagBaobabTree']: + new Map( + directAncestorArtTags + .map(artTag => [artTag, artTag.ancestorArtTagBaobabTree])), + }), + }, + ], +}); diff --git a/src/data/things/art-tag.js b/src/data/things/art-tag.js index 1266a4e0..a530ba8c 100644 --- a/src/data/things/art-tag.js +++ b/src/data/things/art-tag.js @@ -1,17 +1,27 @@ import {input} from '#composite'; -import {sortAlbumsTracksChronologically} from '#wiki-data'; +import find from '#find'; +import {unique} from '#sugar'; import {isName} from '#validators'; +import {sortAlbumsTracksChronologically} from '#wiki-data'; -import {exposeUpdateValueOrContinue} from '#composite/control-flow'; +import {exitWithoutDependency, exposeDependency, exposeUpdateValueOrContinue} + from '#composite/control-flow'; import { color, directory, flag, + referenceList, + reverseReferenceList, + simpleString, name, + urls, wikiData, } from '#composite/wiki-properties'; +import {withAllDescendantArtTags, withAncestorArtTagBaobabTree} + from '#composite/things/art-tag'; + import Thing from './thing.js'; export class ArtTag extends Thing { @@ -24,6 +34,7 @@ export class ArtTag extends Thing { directory: directory(), color: color(), isContentWarning: flag(false), + extraReadingURLs: urls(), nameShort: [ exposeUpdateValueOrContinue({ @@ -37,14 +48,36 @@ export class ArtTag extends Thing { }, ], + description: simpleString(), + + directDescendantArtTags: referenceList({ + class: input.value(ArtTag), + find: input.value(find.artTag), + data: 'artTagData', + }), + // Update only albumData: wikiData(Album), + artTagData: wikiData(ArtTag), trackData: wikiData(Track), // Expose only - taggedInThings: { + descriptionShort: [ + exitWithoutDependency({ + dependency: 'description', + mode: input.value('falsy'), + }), + + { + dependencies: ['description'], + compute: ({description}) => + description.split('<hr class="split">')[0], + }, + ], + + directlyTaggedInThings: { flags: {expose: true}, expose: { @@ -56,5 +89,32 @@ export class ArtTag extends Thing { {getDate: o => o.coverArtDate}), }, }, + + indirectlyTaggedInThings: [ + withAllDescendantArtTags(), + + { + dependencies: ['#allDescendantArtTags'], + compute: ({'#allDescendantArtTags': allDescendantArtTags}) => + unique( + allDescendantArtTags + .flatMap(artTag => artTag.directlyTaggedInThings)), + }, + ], + + allDescendantArtTags: [ + withAllDescendantArtTags(), + exposeDependency({dependency: '#allDescendantArtTags'}), + ], + + directAncestorArtTags: reverseReferenceList({ + data: 'artTagData', + list: input.value('directDescendantArtTags'), + }), + + ancestorArtTagBaobabTree: [ + withAncestorArtTagBaobabTree(), + exposeDependency({dependency: '#ancestorArtTagBaobabTree'}), + ], }); } diff --git a/src/data/things/language.js b/src/data/things/language.js index fe74f7bf..f19a2a1a 100644 --- a/src/data/things/language.js +++ b/src/data/things/language.js @@ -101,6 +101,7 @@ export class Language extends Thing { }, }, + // TODO: This currently isn't used. Is it still needed? strings_htmlEscaped: { flags: {expose: true}, expose: { @@ -130,8 +131,8 @@ export class Language extends Thing { }; } - $(key, args = {}) { - return this.formatString(key, args); + $(...args) { + return this.formatString(...args); } assertIntlAvailable(property) { @@ -145,8 +146,20 @@ export class Language extends Thing { return this.intl_pluralCardinal.select(value); } - formatString(key, args = {}) { - const strings = this.strings_htmlEscaped; + formatString(...args) { + const hasOptions = + typeof args.at(-1) === 'object' && + args.at(-1) !== null; + + const key = + (hasOptions ? args.slice(0, -1) : args) + .filter(Boolean) + .join('.'); + + const options = + (hasOptions + ? args.at(-1) + : null); if (!this.strings) { throw new Error(`Strings unavailable`); @@ -158,27 +171,36 @@ export class Language extends Thing { const template = this.strings[key]; - // Convert the keys on the args dict from camelCase to CONSTANT_CASE. - // (This isn't an OUTRAGEOUSLY versatile algorithm for doing that, 8ut - // like, who cares, dude?) Also, this is an array, 8ecause it's handy - // for the iterating we're a8out to do. Also strip HTML from arguments - // that are literal strings - real HTML content should always be proper - // HTML objects (see html.js). - const processedArgs = - Object.entries(args).map(([k, v]) => [ - k.replace(/[A-Z]/g, '_$&').toUpperCase(), - this.#sanitizeStringArg(v), - ]); - - // Replacement time! Woot. Reduce comes in handy here! - const output = - processedArgs.reduce( - (x, [k, v]) => x.replaceAll(`{${k}}`, v), - template); + let output; + + if (hasOptions) { + // Convert the keys on the options dict from camelCase to CONSTANT_CASE. + // (This isn't an OUTRAGEOUSLY versatile algorithm for doing that, 8ut + // like, who cares, dude?) Also, this is an array, 8ecause it's handy + // for the iterating we're a8out to do. Also strip HTML from arguments + // that are literal strings - real HTML content should always be proper + // HTML objects (see html.js). + const processedOptions = + Object.entries(options).map(([k, v]) => [ + k.replace(/[A-Z]/g, '_$&').toUpperCase(), + this.#sanitizeStringArg(v), + ]); + + // Replacement time! Woot. Reduce comes in handy here! + output = + processedOptions.reduce( + (x, [k, v]) => x.replaceAll(`{${k}}`, v), + template); + } else { + // Without any options provided, just use the template as-is. This will + // still error if the template expected arguments, and otherwise will be + // the right value. + output = template; + } // Post-processing: if any expected arguments *weren't* replaced, that // is almost definitely an error. - if (output.match(/\{[A-Z_]+\}/)) { + if (output.match(/\{[A-Z][A-Z0-9_]*\}/)) { throw new Error(`Args in ${key} were missing - output: ${output}`); } @@ -376,6 +398,7 @@ Object.assign(Language.prototype, { countAdditionalFiles: countHelper('additionalFiles', 'files'), countAlbums: countHelper('albums'), countArtworks: countHelper('artworks'), + countArtTags: countHelper('artTags', 'tags'), countFlashes: countHelper('flashes'), countCommentaryEntries: countHelper('commentaryEntries', 'entries'), countContributions: countHelper('contributions'), diff --git a/src/data/yaml.js b/src/data/yaml.js index c799be5f..09465648 100644 --- a/src/data/yaml.js +++ b/src/data/yaml.js @@ -459,9 +459,13 @@ export const processArtTagDocument = makeProcessDocument(T.ArtTag, { name: 'Tag', nameShort: 'Short Name', directory: 'Directory', + description: 'Description', + extraReadingURLs: 'Extra Reading URLs', color: 'Color', isContentWarning: 'Is CW', + + directDescendantArtTags: 'Direct Descendant Tags', }, }); @@ -1359,7 +1363,7 @@ export function linkWikiDataArrays(wikiData, { assignWikiData(WD.groupCategoryData, 'groupData'); assignWikiData(WD.flashData, 'artistData', 'flashActData', 'trackData'); assignWikiData(WD.flashActData, 'flashData'); - assignWikiData(WD.artTagData, 'albumData', 'trackData'); + assignWikiData(WD.artTagData, 'albumData', 'artTagData', 'trackData'); assignWikiData(WD.homepageLayout?.rows, 'albumData', 'groupData'); } @@ -1477,6 +1481,10 @@ export function filterReferenceErrors(wikiData) { artTags: 'artTag', }], + ['artTagData', processArtTagDocument, { + directDescendantArtTags: 'artTag', + }], + ['trackData', processTrackDocument, { artistContribs: '_contrib', contributorContribs: '_contrib', |