From 1f37e5d6b0c6fccc9c46aabd7bd402375131d452 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 26 Jan 2026 14:07:13 -0400 Subject: data: break up content.js, flash.js, sorting-rule.js --- src/data/things/content/CommentaryEntry.js | 20 ++ src/data/things/content/ContentEntry.js | 246 +++++++++++++++++++++ src/data/things/content/CreditingSourcesEntry.js | 16 ++ src/data/things/content/LyricsEntry.js | 43 ++++ src/data/things/content/ReferencingSourcesEntry.js | 16 ++ src/data/things/content/index.js | 9 + 6 files changed, 350 insertions(+) create mode 100644 src/data/things/content/CommentaryEntry.js create mode 100644 src/data/things/content/ContentEntry.js create mode 100644 src/data/things/content/CreditingSourcesEntry.js create mode 100644 src/data/things/content/LyricsEntry.js create mode 100644 src/data/things/content/ReferencingSourcesEntry.js create mode 100644 src/data/things/content/index.js (limited to 'src/data/things/content') diff --git a/src/data/things/content/CommentaryEntry.js b/src/data/things/content/CommentaryEntry.js new file mode 100644 index 00000000..32d69213 --- /dev/null +++ b/src/data/things/content/CommentaryEntry.js @@ -0,0 +1,20 @@ +import {V} from '#composite'; +import Thing from '#thing'; + +import {exposeConstant} from '#composite/control-flow'; + +import {hasAnnotationPart} from '#composite/things/content'; + +import {ContentEntry} from './ContentEntry.js'; + +export class CommentaryEntry extends ContentEntry { + static [Thing.wikiData] = 'commentaryData'; + + static [Thing.getPropertyDescriptors] = () => ({ + // Expose only + + isCommentaryEntry: exposeConstant(V(true)), + + isWikiEditorCommentary: hasAnnotationPart(V('wiki editor')), + }); +} diff --git a/src/data/things/content/ContentEntry.js b/src/data/things/content/ContentEntry.js new file mode 100644 index 00000000..7dc81345 --- /dev/null +++ b/src/data/things/content/ContentEntry.js @@ -0,0 +1,246 @@ +import {input, V} from '#composite'; +import {transposeArrays} from '#sugar'; +import Thing from '#thing'; +import {is, isDate, validateReferenceList} from '#validators'; +import {parseDate} from '#yaml'; + +import {withFilteredList, withMappedList, withPropertyFromList} + from '#composite/data'; +import {withResolvedReferenceList} from '#composite/wiki-data'; +import {contentString, simpleDate, soupyFind, thing} + from '#composite/wiki-properties'; + +import { + exitWithoutDependency, + exposeConstant, + exposeDependency, + exposeDependencyOrContinue, + exposeUpdateValueOrContinue, + withResultOfAvailabilityCheck, +} from '#composite/control-flow'; + +import { + withAnnotationPartNodeLists, + withExpressedOrImplicitArtistReferences, + withWebArchiveDate, +} from '#composite/things/content'; + +export class ContentEntry extends Thing { + static [Thing.getPropertyDescriptors] = () => ({ + // Update & expose + + thing: thing(), + + artists: [ + withExpressedOrImplicitArtistReferences({ + from: input.updateValue({ + validate: validateReferenceList('artist'), + }), + }), + + exitWithoutDependency('#artistReferences', V([])), + + withResolvedReferenceList({ + list: '#artistReferences', + find: soupyFind.input('artist'), + }), + + exposeDependency('#resolvedReferenceList'), + ], + + artistText: contentString(), + + annotation: contentString(), + + dateKind: { + flags: {update: true, expose: true}, + + update: { + validate: is(...[ + 'sometime', + 'throughout', + 'around', + ]), + }, + }, + + accessKind: [ + exitWithoutDependency('_accessDate'), + + exposeUpdateValueOrContinue({ + validate: input.value( + is(...[ + 'captured', + 'accessed', + ])), + }), + + withWebArchiveDate(), + + withResultOfAvailabilityCheck({from: '#webArchiveDate'}), + + { + dependencies: ['#availability'], + compute: (continuation, {['#availability']: availability}) => + (availability + ? continuation.exit('captured') + : continuation()), + }, + + exposeConstant(V('accessed')), + ], + + date: simpleDate(), + secondDate: simpleDate(), + + accessDate: [ + exposeUpdateValueOrContinue({ + validate: input.value(isDate), + }), + + withWebArchiveDate(), + + exposeDependencyOrContinue({ + dependency: '#webArchiveDate', + }), + + exposeConstant(V(null)), + ], + + body: contentString(), + + // Update only + + find: soupyFind(), + + // Expose only + + isContentEntry: exposeConstant(V(true)), + + annotationParts: [ + withAnnotationPartNodeLists(), + + { + dependencies: ['#annotationPartNodeLists'], + compute: (continuation, { + ['#annotationPartNodeLists']: nodeLists, + }) => continuation({ + ['#firstNodes']: + nodeLists.map(list => list.at(0)), + + ['#lastNodes']: + nodeLists.map(list => list.at(-1)), + }), + }, + + withPropertyFromList('#firstNodes', V('i')) + .outputs({'#firstNodes.i': '#startIndices'}), + + withPropertyFromList('#lastNodes', V('iEnd')) + .outputs({'#lastNodes.iEnd': '#endIndices'}), + + { + dependencies: [ + 'annotation', + '#startIndices', + '#endIndices', + ], + + compute: ({ + ['annotation']: annotation, + ['#startIndices']: startIndices, + ['#endIndices']: endIndices, + }) => + transposeArrays([startIndices, endIndices]) + .map(([start, end]) => + annotation.slice(start, end)), + }, + ], + + sourceText: [ + withAnnotationPartNodeLists(), + + { + dependencies: ['#annotationPartNodeLists'], + compute: (continuation, { + ['#annotationPartNodeLists']: nodeLists, + }) => continuation({ + ['#firstPartWithExternalLink']: + nodeLists + .find(nodes => nodes + .some(node => node.type === 'external-link')) ?? + null, + }), + }, + + exitWithoutDependency('#firstPartWithExternalLink'), + + { + dependencies: ['annotation', '#firstPartWithExternalLink'], + compute: ({ + ['annotation']: annotation, + ['#firstPartWithExternalLink']: nodes, + }) => + annotation.slice( + nodes.at(0).i, + nodes.at(-1).iEnd), + }, + ], + + sourceURLs: [ + withAnnotationPartNodeLists(), + + { + dependencies: ['#annotationPartNodeLists'], + compute: (continuation, { + ['#annotationPartNodeLists']: nodeLists, + }) => continuation({ + ['#firstPartWithExternalLink']: + nodeLists + .find(nodes => nodes + .some(node => node.type === 'external-link')) ?? + null, + }), + }, + + exitWithoutDependency('#firstPartWithExternalLink', V([])), + + withMappedList({ + list: '#firstPartWithExternalLink', + map: input.value(node => node.type === 'external-link'), + }).outputs({ + '#mappedList': '#externalLinkFilter', + }), + + withFilteredList({ + list: '#firstPartWithExternalLink', + filter: '#externalLinkFilter', + }), + + withMappedList({ + list: '#filteredList', + map: input.value(node => node.data.href), + }), + + exposeDependency('#mappedList'), + ], + }); + + static [Thing.yamlDocumentSpec] = { + fields: { + 'Artists': {property: 'artists'}, + 'Artist Text': {property: 'artistText'}, + + 'Annotation': {property: 'annotation'}, + + 'Date Kind': {property: 'dateKind'}, + 'Access Kind': {property: 'accessKind'}, + + 'Date': {property: 'date', transform: parseDate}, + 'Second Date': {property: 'secondDate', transform: parseDate}, + 'Access Date': {property: 'accessDate', transform: parseDate}, + + 'Body': {property: 'body'}, + }, + }; +} diff --git a/src/data/things/content/CreditingSourcesEntry.js b/src/data/things/content/CreditingSourcesEntry.js new file mode 100644 index 00000000..7331ae8c --- /dev/null +++ b/src/data/things/content/CreditingSourcesEntry.js @@ -0,0 +1,16 @@ +import {V} from '#composite'; +import Thing from '#thing'; + +import {exposeConstant} from '#composite/control-flow'; + +import {ContentEntry} from './ContentEntry.js'; + +export class CreditingSourcesEntry extends ContentEntry { + static [Thing.wikiData] = 'creditingSourceData'; + + static [Thing.getPropertyDescriptors] = () => ({ + // Expose only + + isCreditingSourcesEntry: exposeConstant(V(true)), + }); +} diff --git a/src/data/things/content/LyricsEntry.js b/src/data/things/content/LyricsEntry.js new file mode 100644 index 00000000..88e4464d --- /dev/null +++ b/src/data/things/content/LyricsEntry.js @@ -0,0 +1,43 @@ +import {V} from '#composite'; +import Thing from '#thing'; + +import {exitWithoutDependency, exposeConstant} from '#composite/control-flow'; +import {contentString} from '#composite/wiki-properties'; + +import {hasAnnotationPart} from '#composite/things/content'; + +import {ContentEntry} from './ContentEntry.js'; + +export class LyricsEntry extends ContentEntry { + static [Thing.wikiData] = 'lyricsData'; + + static [Thing.getPropertyDescriptors] = () => ({ + // Update & expose + + originDetails: contentString(), + + // Expose only + + isLyricsEntry: exposeConstant(V(true)), + + isWikiLyrics: hasAnnotationPart(V('wiki lyrics')), + helpNeeded: hasAnnotationPart(V('help needed')), + + hasSquareBracketAnnotations: [ + exitWithoutDependency('isWikiLyrics', V(false), V('falsy')), + exitWithoutDependency('body', V(false)), + + { + dependencies: ['body'], + compute: ({body}) => + /\[.*\]/m.test(body), + }, + ], + }); + + static [Thing.yamlDocumentSpec] = Thing.extendDocumentSpec(ContentEntry, { + fields: { + 'Origin Details': {property: 'originDetails'}, + }, + }); +} diff --git a/src/data/things/content/ReferencingSourcesEntry.js b/src/data/things/content/ReferencingSourcesEntry.js new file mode 100644 index 00000000..76fafbc2 --- /dev/null +++ b/src/data/things/content/ReferencingSourcesEntry.js @@ -0,0 +1,16 @@ +import {V} from '#composite'; +import Thing from '#thing'; + +import {exposeConstant} from '#composite/control-flow'; + +import {ContentEntry} from './ContentEntry.js'; + +export class ReferencingSourcesEntry extends ContentEntry { + static [Thing.wikiData] = 'referencingSourceData'; + + static [Thing.getPropertyDescriptors] = () => ({ + // Expose only + + isReferencingSourceEntry: exposeConstant(V(true)), + }); +} diff --git a/src/data/things/content/index.js b/src/data/things/content/index.js new file mode 100644 index 00000000..aaa7f304 --- /dev/null +++ b/src/data/things/content/index.js @@ -0,0 +1,9 @@ +// Yet Another Index.js File Descending From A Folder Named Content + +export * from './ContentEntry.js'; + +export * from './CommentaryEntry.js'; +export * from './LyricsEntry.js'; + +export * from './CreditingSourcesEntry.js'; +export * from './ReferencingSourcesEntry.js'; -- cgit 1.3.0-6-gf8a5