diff options
Diffstat (limited to 'src/data/composite/wiki-data')
-rw-r--r-- | src/data/composite/wiki-data/index.js | 8 | ||||
-rw-r--r-- | src/data/composite/wiki-data/withParsedCommentaryEntries.js | 179 | ||||
-rw-r--r-- | src/data/composite/wiki-data/withThingsSortedAlphabetically.js | 122 |
3 files changed, 309 insertions, 0 deletions
diff --git a/src/data/composite/wiki-data/index.js b/src/data/composite/wiki-data/index.js index 1d0400fc..a2ff09d8 100644 --- a/src/data/composite/wiki-data/index.js +++ b/src/data/composite/wiki-data/index.js @@ -1,7 +1,15 @@ +// #composite/wiki-data +// +// Entries here may depend on entries in #composite/control-flow and in +// #composite/data. +// + export {default as exitWithoutContribs} from './exitWithoutContribs.js'; export {default as inputThingClass} from './inputThingClass.js'; export {default as inputWikiData} from './inputWikiData.js'; +export {default as withParsedCommentaryEntries} from './withParsedCommentaryEntries.js'; export {default as withResolvedContribs} from './withResolvedContribs.js'; export {default as withResolvedReference} from './withResolvedReference.js'; export {default as withResolvedReferenceList} from './withResolvedReferenceList.js'; export {default as withReverseReferenceList} from './withReverseReferenceList.js'; +export {default as withThingsSortedAlphabetically} from './withThingsSortedAlphabetically.js'; diff --git a/src/data/composite/wiki-data/withParsedCommentaryEntries.js b/src/data/composite/wiki-data/withParsedCommentaryEntries.js new file mode 100644 index 00000000..edfc9e3c --- /dev/null +++ b/src/data/composite/wiki-data/withParsedCommentaryEntries.js @@ -0,0 +1,179 @@ +import {input, templateCompositeFrom} from '#composite'; +import find from '#find'; +import {stitchArrays} from '#sugar'; +import {isCommentary} from '#validators'; +import {commentaryRegex} from '#wiki-data'; + +import { + fillMissingListItems, + withFlattenedList, + withPropertiesFromList, + withUnflattenedList, +} from '#composite/data'; + +import withResolvedReferenceList from './withResolvedReferenceList.js'; + +export default templateCompositeFrom({ + annotation: `withParsedCommentaryEntries`, + + inputs: { + from: input({validate: isCommentary}), + }, + + outputs: ['#parsedCommentaryEntries'], + + steps: () => [ + { + dependencies: [input('from')], + + compute: (continuation, { + [input('from')]: commentaryText, + }) => continuation({ + ['#rawMatches']: + Array.from(commentaryText.matchAll(commentaryRegex)), + }), + }, + + withPropertiesFromList({ + list: '#rawMatches', + properties: input.value([ + '0', // The entire match as a string. + 'groups', + 'index', + ]), + }).outputs({ + '#rawMatches.0': '#rawMatches.text', + '#rawMatches.groups': '#rawMatches.groups', + '#rawMatches.index': '#rawMatches.startIndex', + }), + + { + dependencies: [ + '#rawMatches.text', + '#rawMatches.startIndex', + ], + + compute: (continuation, { + ['#rawMatches.text']: text, + ['#rawMatches.startIndex']: startIndex, + }) => continuation({ + ['#rawMatches.endIndex']: + stitchArrays({text, startIndex}) + .map(({text, startIndex}) => startIndex + text.length), + }), + }, + + { + dependencies: [ + input('from'), + '#rawMatches.startIndex', + '#rawMatches.endIndex', + ], + + compute: (continuation, { + [input('from')]: commentaryText, + ['#rawMatches.startIndex']: startIndex, + ['#rawMatches.endIndex']: endIndex, + }) => continuation({ + ['#entries.body']: + stitchArrays({startIndex, endIndex}) + .map(({endIndex}, index, stitched) => + (index === stitched.length - 1 + ? commentaryText.slice(endIndex) + : commentaryText.slice( + endIndex, + stitched[index + 1].startIndex))) + .map(body => body.trim()), + }), + }, + + withPropertiesFromList({ + list: '#rawMatches.groups', + prefix: input.value('#entries'), + properties: input.value([ + 'artistReferences', + 'artistDisplayText', + 'annotation', + 'date', + ]), + }), + + // The artistReferences group will always have a value, since it's required + // for the line to match in the first place. + + { + dependencies: ['#entries.artistReferences'], + compute: (continuation, { + ['#entries.artistReferences']: artistReferenceTexts, + }) => continuation({ + ['#entries.artistReferences']: + artistReferenceTexts + .map(text => text.split(',').map(ref => ref.trim())), + }), + }, + + withFlattenedList({ + list: '#entries.artistReferences', + }), + + withResolvedReferenceList({ + list: '#flattenedList', + data: 'artistData', + find: input.value(find.artist), + notFoundMode: input.value('null'), + }), + + withUnflattenedList({ + list: '#resolvedReferenceList', + }).outputs({ + '#unflattenedList': '#entries.artists', + }), + + fillMissingListItems({ + list: '#entries.artistDisplayText', + fill: input.value(null), + }), + + fillMissingListItems({ + list: '#entries.annotation', + fill: input.value(null), + }), + + { + dependencies: ['#entries.date'], + compute: (continuation, { + ['#entries.date']: date, + }) => continuation({ + ['#entries.date']: + date.map(date => date ? new Date(date) : null), + }), + }, + + { + dependencies: [ + '#entries.artists', + '#entries.artistDisplayText', + '#entries.annotation', + '#entries.date', + '#entries.body', + ], + + compute: (continuation, { + ['#entries.artists']: artists, + ['#entries.artistDisplayText']: artistDisplayText, + ['#entries.annotation']: annotation, + ['#entries.date']: date, + ['#entries.body']: body, + }) => continuation({ + ['#parsedCommentaryEntries']: + stitchArrays({ + artists, + artistDisplayText, + annotation, + date, + body, + }), + }), + }, + ], +}); diff --git a/src/data/composite/wiki-data/withThingsSortedAlphabetically.js b/src/data/composite/wiki-data/withThingsSortedAlphabetically.js new file mode 100644 index 00000000..d2487e42 --- /dev/null +++ b/src/data/composite/wiki-data/withThingsSortedAlphabetically.js @@ -0,0 +1,122 @@ +// Sorts a list of live, generic wiki data objects alphabetically. +// Note that this uses localeCompare but isn't specialized to a particular +// language; where localization is concerned (in content), a follow-up, locale- +// specific sort should be performed. But this function does serve to organize +// a list so same-name entries are beside each other. + +import {input, templateCompositeFrom} from '#composite'; +import {validateWikiData} from '#validators'; +import {compareCaseLessSensitive, normalizeName} from '#wiki-data'; + +import {raiseOutputWithoutDependency} from '#composite/control-flow'; +import {withMappedList, withSortedList, withPropertiesFromList} + from '#composite/data'; + +export default templateCompositeFrom({ + annotation: `withThingsSortedAlphabetically`, + + inputs: { + things: input({validate: validateWikiData}), + }, + + outputs: ['#sortedThings'], + + steps: () => [ + raiseOutputWithoutDependency({ + dependency: input('things'), + mode: input.value('empty'), + output: input.value({'#sortedThings': []}), + }), + + withPropertiesFromList({ + list: input('things'), + properties: input.value(['name', 'directory']), + }).outputs({ + '#list.name': '#names', + '#list.directory': '#directories', + }), + + withMappedList({ + list: '#names', + map: input.value(normalizeName), + }).outputs({ + '#mappedList': '#normalizedNames', + }), + + withSortedList({ + list: '#normalizedNames', + sort: input.value(compareCaseLessSensitive), + }).outputs({ + '#unstableSortIndices': '#normalizedNameSortIndices', + }), + + withSortedList({ + list: '#names', + sort: input.value(compareCaseLessSensitive), + }).outputs({ + '#unstableSortIndices': '#nonNormalizedNameSortIndices', + }), + + withSortedList({ + list: '#directories', + sort: input.value(compareCaseLessSensitive), + }).outputs({ + '#unstableSortIndices': '#directorySortIndices', + }), + + // TODO: No primitive for the next two-three steps, yet... + + { + dependencies: [input('things')], + compute: (continuation, { + [input('things')]: things, + }) => continuation({ + ['#combinedSortIndices']: + Array.from( + {length: things.length}, + (_item, index) => index), + }), + }, + + { + dependencies: [ + '#combinedSortIndices', + '#normalizedNameSortIndices', + '#nonNormalizedNameSortIndices', + '#directorySortIndices', + ], + + compute: (continuation, { + ['#combinedSortIndices']: combined, + ['#normalizedNameSortIndices']: normalized, + ['#nonNormalizedNameSortIndices']: nonNormalized, + ['#directorySortIndices']: directory, + }) => continuation({ + ['#combinedSortIndices']: + combined.sort((index1, index2) => { + if (normalized[index1] !== normalized[index2]) + return normalized[index1] - normalized[index2]; + + if (nonNormalized[index1] !== nonNormalized[index2]) + return nonNormalized[index1] - nonNormalized[index2]; + + if (directory[index1] !== directory[index2]) + return directory[index1] - directory[index2]; + + return 0; + }), + }), + }, + + { + dependencies: [input('things'), '#combinedSortIndices'], + compute: (continuation, { + [input('things')]: things, + ['#combinedSortIndices']: combined, + }) => continuation({ + ['#sortedThings']: + combined.map(index => things[index]), + }), + }, + ], +}); |