diff options
Diffstat (limited to 'src/data/things')
-rw-r--r-- | src/data/things/art-tag.js | 66 | ||||
-rw-r--r-- | src/data/things/language.js | 67 |
2 files changed, 108 insertions, 25 deletions
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'), |