diff options
Diffstat (limited to 'src/data')
| -rw-r--r-- | src/data/checks.js | 7 | ||||
| -rw-r--r-- | src/data/composite.js | 32 | ||||
| -rw-r--r-- | src/data/composite/things/content/withExpressedOrImplicitArtistReferences.js | 29 | ||||
| -rw-r--r-- | src/data/things/content/ContentEntry.js | 53 |
4 files changed, 91 insertions, 30 deletions
diff --git a/src/data/checks.js b/src/data/checks.js index 0a0e7f52..01b5cf9e 100644 --- a/src/data/checks.js +++ b/src/data/checks.js @@ -352,6 +352,9 @@ export function filterReferenceErrors(wikiData, { switch (findFnKey) { case '_content': + // note: quoted artists ("Quoted Artists" field)`) currently + // not handled here at all. limitation of current code! oops! + if (value) { value = value.map(entry => @@ -721,13 +724,13 @@ export function reportContentTextErrors(wikiData, { const commentaryShape = { body: 'commentary body', - artistText: 'commentary artist text', + headingArtistText: 'commentary artist text', annotation: 'commentary annotation', }; const lyricsShape = { body: 'lyrics body', - artistText: 'lyrics artist text', + headingArtistText: 'lyrics artist text', annotation: 'lyrics annotation', }; diff --git a/src/data/composite.js b/src/data/composite.js index 8ac906c7..3b462ef5 100644 --- a/src/data/composite.js +++ b/src/data/composite.js @@ -10,17 +10,27 @@ import {TupleMap} from '#wiki-data'; const globalCompositeCache = {}; -const _valueIntoToken = shape => - (value = null) => - (value === null - ? Symbol.for(`hsmusic.composite.${shape}`) - : typeof value === 'string' - ? Symbol.for(`hsmusic.composite.${shape}:${value}`) - : { - symbol: Symbol.for(`hsmusic.composite.${shape.split('.')[0]}`), - shape, - value, - }); +const _valueIntoToken = shape => (value = null) => { + if (value === null) { + return Symbol.for(`hsmusic.composite.${shape}`); + } + + if (typeof value === 'string') { + return Symbol.for(`hsmusic.composite.${shape}:${value}`); + } + + if (typeof value === 'object') { + if (Object.values(value).some(isInputToken)) { + throw new TypeError(`Don't nest input tokens inside ${shape}()`); + } + } + + return { + symbol: Symbol.for(`hsmusic.composite.${shape.split('.')[0]}`), + shape, + value, + }; +}; export const input = _valueIntoToken('input'); input.symbol = Symbol.for('hsmusic.composite.input'); diff --git a/src/data/composite/things/content/withExpressedOrImplicitArtistReferences.js b/src/data/composite/things/content/withExpressedOrImplicitArtistReferences.js index 69da8c75..a6200ee8 100644 --- a/src/data/composite/things/content/withExpressedOrImplicitArtistReferences.js +++ b/src/data/composite/things/content/withExpressedOrImplicitArtistReferences.js @@ -8,16 +8,19 @@ export default templateCompositeFrom({ annotation: `withExpressedOrImplicitArtistReferences`, inputs: { - from: input({type: 'array', acceptsNull: true}), + fromExpressed: input({type: 'array', acceptsNull: true}), + fromContent: input({type: 'string', acceptsNull: true}), + + filterArtistTags: input({type: 'function', defaultValue: () => true}), }, outputs: ['#artistReferences'], steps: () => [ { - dependencies: [input('from')], + dependencies: [input('fromExpressed')], compute: (continuation, { - [input('from')]: expressedArtistReferences, + [input('fromExpressed')]: expressedArtistReferences, }) => (expressedArtistReferences ? continuation.raiseOutput({'#artistReferences': expressedArtistReferences}) @@ -25,12 +28,12 @@ export default templateCompositeFrom({ }, raiseOutputWithoutDependency({ - dependency: 'artistText', - output: input.value({'#artistReferences': null}), + dependency: input('fromContent'), + output: input.value({'#artistReferences': []}), }), withContentNodes({ - from: 'artistText', + from: input('fromContent'), }), withMappedList({ @@ -42,13 +45,19 @@ export default templateCompositeFrom({ '#mappedList': '#artistTagFilter', }), - withFilteredList({ - list: '#contentNodes', - filter: '#artistTagFilter', + withFilteredList('#contentNodes', '#artistTagFilter') + .outputs({'#filteredList': '#artistTags'}), + + withMappedList({ + list: '#artistTags', + map: input('filterArtistTags'), }).outputs({ - '#filteredList': '#artistTags', + '#mappedList': '#customFilter', }), + withFilteredList({list: '#artistTags', filter: '#customFilter'}) + .outputs({'#filteredList': '#artistTags'}), + withMappedList({ list: '#artistTags', map: input.value(node => diff --git a/src/data/things/content/ContentEntry.js b/src/data/things/content/ContentEntry.js index 04df303f..47f86622 100644 --- a/src/data/things/content/ContentEntry.js +++ b/src/data/things/content/ContentEntry.js @@ -1,5 +1,5 @@ import {input, V} from '#composite'; -import {transposeArrays} from '#sugar'; +import {transposeArrays, unique} from '#sugar'; import Thing from '#thing'; import {is, isDate, validateReferenceList} from '#validators'; import {parseDate} from '#yaml'; @@ -33,14 +33,43 @@ export class ContentEntry extends Thing { thing: thing(), - artists: [ + headingArtists: [ withExpressedOrImplicitArtistReferences({ - from: input.updateValue({ + fromExpressed: input.updateValue({ validate: validateReferenceList('artist'), }), + + fromContent: 'headingArtistText', + }), + + withResolvedReferenceList({ + list: '#artistReferences', + find: soupyFind.input('artist'), }), - exitWithoutDependency('#artistReferences', V([])), + exposeDependency('#resolvedReferenceList'), + ], + + quotedArtists: [ + exitWithoutDependency('body', V([])), + + { + dependencies: ['body'], + compute: (continuation, {body}) => continuation({ + ['#filterArtistTags']: node => + /(\n|^)> <i>$/.test(body.slice(0, node.i)) && + /^:<\/i>/.test(body.slice(node.iEnd)), + }), + }, + + withExpressedOrImplicitArtistReferences({ + fromExpressed: input.updateValue({ + validate: validateReferenceList('artist'), + }), + + fromContent: 'body', + filterArtistTags: '#filterArtistTags', + }), withResolvedReferenceList({ list: '#artistReferences', @@ -50,7 +79,7 @@ export class ContentEntry extends Thing { exposeDependency('#resolvedReferenceList'), ], - artistText: contentString(), + headingArtistText: contentString(), annotation: contentString(), @@ -119,6 +148,14 @@ export class ContentEntry extends Thing { isContentEntry: exposeConstant(V(true)), + artists: [ + { + dependencies: ['headingArtists', 'quotedArtists'], + compute: ({headingArtists, quotedArtists}) => + unique([...headingArtists, ...quotedArtists]), + }, + ], + annotationParts: [ withAnnotationPartNodeLists(), @@ -230,8 +267,10 @@ export class ContentEntry extends Thing { static [Thing.yamlDocumentSpec] = { fields: { - 'Artists': {property: 'artists'}, - 'Artist Text': {property: 'artistText'}, + 'Artists': {property: 'headingArtists'}, + 'Artist Text': {property: 'headingArtistText'}, + + 'Quoted Artists': {property: 'quotedArtists'}, 'Annotation': {property: 'annotation'}, |