diff options
22 files changed, 106 insertions, 45 deletions
diff --git a/src/content/dependencies/generateAlbumCommentaryPage.js b/src/content/dependencies/generateAlbumCommentaryPage.js index b6c8edf6..a380f468 100644 --- a/src/content/dependencies/generateAlbumCommentaryPage.js +++ b/src/content/dependencies/generateAlbumCommentaryPage.js @@ -51,7 +51,8 @@ export default { relation('linkAlbum', album); relations.albumCommentaryListeningLinks = - album.urls.map(url => relation('linkExternal', url)); + album.urls + .map(entry => relation('linkExternal', entry.url)); if (album.hasCoverArt) { relations.albumCommentaryCover = @@ -74,7 +75,7 @@ export default { relations.trackCommentaryListeningLinks = query.tracksWithCommentary .map(track => - track.urls.map(url => relation('linkExternal', url))); + track.urls.map(entry => relation('linkExternal', entry.url))); relations.trackCommentaryCovers = query.tracksWithCommentary diff --git a/src/content/dependencies/generateAlbumSidebarGroupBox.js b/src/content/dependencies/generateAlbumSidebarGroupBox.js index 0a9c0db9..15fedf75 100644 --- a/src/content/dependencies/generateAlbumSidebarGroupBox.js +++ b/src/content/dependencies/generateAlbumSidebarGroupBox.js @@ -38,8 +38,8 @@ export default { relation('linkGroup', group); relations.externalLinks = - group.urls.map(url => - relation('linkExternal', url)); + group.urls + .map(entry => relation('linkExternal', entry.url)); if (group.descriptionShort) { relations.description = diff --git a/src/content/dependencies/generateArtTagGalleryPage.js b/src/content/dependencies/generateArtTagGalleryPage.js index 646975ef..ec0624d1 100644 --- a/src/content/dependencies/generateArtTagGalleryPage.js +++ b/src/content/dependencies/generateArtTagGalleryPage.js @@ -42,7 +42,7 @@ export default { if (!empty(artTag.extraReadingURLs)) { relations.extraReadingLinks = artTag.extraReadingURLs - .map(url => relation('linkExternal', url)); + .map(entry => relation('linkExternal', entry.url)); } if (!empty(artTag.directAncestorArtTags)) { diff --git a/src/content/dependencies/generateArtTagInfoPage.js b/src/content/dependencies/generateArtTagInfoPage.js index 683eeab6..db26260b 100644 --- a/src/content/dependencies/generateArtTagInfoPage.js +++ b/src/content/dependencies/generateArtTagInfoPage.js @@ -50,7 +50,7 @@ export default { extraReadingLinks: artTag.extraReadingURLs - .map(url => relation('linkExternal', url)), + .map(entry => relation('linkExternal', entry.url)), relatedArtTagLinks: artTag.relatedArtTags diff --git a/src/content/dependencies/generateArtistInfoPage.js b/src/content/dependencies/generateArtistInfoPage.js index 29bc34e6..3961dc49 100644 --- a/src/content/dependencies/generateArtistInfoPage.js +++ b/src/content/dependencies/generateArtistInfoPage.js @@ -62,7 +62,7 @@ export default { visitLinks: artist.urls - .map(url => relation('linkExternal', url)), + .map(entry => relation('linkExternal', entry.url)), tracksChunkedList: relation('generateArtistInfoPageTracksChunkedList', artist), diff --git a/src/content/dependencies/generateArtistInfoPageMusicVideosChunkItem.js b/src/content/dependencies/generateArtistInfoPageMusicVideosChunkItem.js index 8bae860d..570a984a 100644 --- a/src/content/dependencies/generateArtistInfoPageMusicVideosChunkItem.js +++ b/src/content/dependencies/generateArtistInfoPageMusicVideosChunkItem.js @@ -38,7 +38,7 @@ export default { externalLinks: query.musicVideo.urls - .map(url => relation('linkExternal', url)), + .map(entry => relation('linkExternal', entry.url)), }), data: (query, _artist, contribs) => ({ diff --git a/src/content/dependencies/generateContributionTooltipExternalLinkSection.js b/src/content/dependencies/generateContributionTooltipExternalLinkSection.js index 210db1e9..cc61fab4 100644 --- a/src/content/dependencies/generateContributionTooltipExternalLinkSection.js +++ b/src/content/dependencies/generateContributionTooltipExternalLinkSection.js @@ -4,19 +4,21 @@ export default { relations: (relation, contribution) => ({ icons: contribution.artist.urls - .map(url => relation('generateExternalIcon', url)), + .map(entry => relation('generateExternalIcon', entry.url)), handles: contribution.artist.urls - .map(url => relation('generateExternalHandle', url)), + .map(entry => relation('generateExternalHandle', entry.url)), platforms: contribution.artist.urls - .map(url => relation('generateExternalPlatform', url)), + .map(entry => relation('generateExternalPlatform', entry.url)), }), data: (contribution) => ({ - urls: contribution.artist.urls, + urls: + contribution.artist.urls + .map(entry => entry.url), }), generate: (data, relations, {html, language}) => diff --git a/src/content/dependencies/generateFlashInfoPage.js b/src/content/dependencies/generateFlashInfoPage.js index b4e8c757..b334412b 100644 --- a/src/content/dependencies/generateFlashInfoPage.js +++ b/src/content/dependencies/generateFlashInfoPage.js @@ -42,7 +42,7 @@ export default { externalLinks: query.urls - .map(url => relation('linkExternal', url)), + .map(entry => relation('linkExternal', entry.url)), artworkColumn: relation('generateFlashArtworkColumn', flash), diff --git a/src/content/dependencies/generateGroupInfoPage.js b/src/content/dependencies/generateGroupInfoPage.js index 0f3093b2..261d2212 100644 --- a/src/content/dependencies/generateGroupInfoPage.js +++ b/src/content/dependencies/generateGroupInfoPage.js @@ -51,7 +51,7 @@ export default { visitLinks: group.urls - .map(url => relation('linkExternal', url)), + .map(entry => relation('linkExternal', entry.url)), description: relation('transformContent', group.description), diff --git a/src/content/dependencies/generateMusicVideo.js b/src/content/dependencies/generateMusicVideo.js index e00b83b0..15eb233b 100644 --- a/src/content/dependencies/generateMusicVideo.js +++ b/src/content/dependencies/generateMusicVideo.js @@ -21,7 +21,7 @@ export default { watchLinks: musicVideo.urls - .map(url => relation('linkExternal', url)), + .map(entry => relation('linkExternal', entry.url)), }), data: (musicVideo, _thing) => ({ diff --git a/src/content/dependencies/generateReleaseInfoListenLine.js b/src/content/dependencies/generateReleaseInfoListenLine.js index 97f248d6..cd3baaf2 100644 --- a/src/content/dependencies/generateReleaseInfoListenLine.js +++ b/src/content/dependencies/generateReleaseInfoListenLine.js @@ -64,7 +64,8 @@ export default { relations: (relation, query, _thing) => ({ links: - query.urls.map(url => relation('linkExternal', url)), + query.urls + .map(entry => relation('linkExternal', entry.url)), }), data(query, thing) { @@ -76,13 +77,13 @@ export default { unique([ ...query.artists.flatMap(artist => artist.urls), ...query.artistGroups.flatMap(group => group.urls), - ]).map(url => new URL(url)); + ]).map(entry => new URL(entry.url)); const albumArtistURLs = unique([ ...query.albumArtists.flatMap(artist => artist.urls), ...query.albumArtistGroups.flatMap(group => group.urls), - ]).map(url => new URL(url)); + ]).map(entry => new URL(entry.url)); const boundGetReleaseContext = urlString => getReleaseContext(urlString, { @@ -91,10 +92,10 @@ export default { }); let releaseContexts = - query.urls.map(boundGetReleaseContext); + query.urls.map(({url}) => boundGetReleaseContext(url)); const albumReleaseContexts = - query.album.urls.map(boundGetReleaseContext); + query.album.urls.map(({url}) => boundGetReleaseContext(url)); const presentReleaseContexts = unique(releaseContexts.filter(Boolean)); diff --git a/src/data/composite/wiki-properties/simpleDate.js b/src/data/composite/wiki-properties/simpleDate.js index f08d8323..238b906f 100644 --- a/src/data/composite/wiki-properties/simpleDate.js +++ b/src/data/composite/wiki-properties/simpleDate.js @@ -4,8 +4,6 @@ import {isDate} from '#validators'; -// TODO: Not templateCompositeFrom. - export default function() { return { flags: {update: true, expose: true}, diff --git a/src/data/composite/wiki-properties/urls.js b/src/data/composite/wiki-properties/urls.js index 04ccf689..5525b462 100644 --- a/src/data/composite/wiki-properties/urls.js +++ b/src/data/composite/wiki-properties/urls.js @@ -1,14 +1,13 @@ // A list of URLs! This will always be present on the data object, even if set // to an empty array or null. -import {isCuratedURL, validateArrayItems} from '#validators'; - -// TODO: Not templateCompositeFrom. +import {isCuratedURLList} from '#validators'; +import {templateCompositeFrom} from '#composite'; export default function() { return { flags: {update: true, expose: true}, - update: {validate: validateArrayItems(isCuratedURL)}, + update: {validate: isCuratedURLList}, expose: {transform: value => value ?? []}, }; } diff --git a/src/data/things/ArtTag.js b/src/data/things/ArtTag.js index 9d35f54d..1da32b0a 100644 --- a/src/data/things/ArtTag.js +++ b/src/data/things/ArtTag.js @@ -2,7 +2,8 @@ import {input, V} from '#composite'; import Thing from '#thing'; import {unique} from '#sugar'; import {isName} from '#validators'; -import {parseAdditionalNames, parseAnnotatedReferences} from '#yaml'; +import {parseAdditionalNames, parseAnnotatedReferences, parseURLs} + from '#yaml'; import { exitWithoutDependency, @@ -170,7 +171,11 @@ export class ArtTag extends Thing { 'Short Name': {property: 'nameShort'}, 'Directory': {property: 'directory'}, 'Description': {property: 'description'}, - 'Extra Reading URLs': {property: 'extraReadingURLs'}, + + 'Extra Reading URLs': { + property: 'extraReadingURLs', + transform: parseURLs, + }, 'Additional Names': { property: 'additionalNames', diff --git a/src/data/things/Artist.js b/src/data/things/Artist.js index 6ce448ff..64798527 100644 --- a/src/data/things/Artist.js +++ b/src/data/things/Artist.js @@ -4,7 +4,7 @@ import CacheableObject from '#cacheable-object'; import {colors} from '#cli'; import {input, V} from '#composite'; import Thing from '#thing'; -import {parseArtistAliases, parseArtwork} from '#yaml'; +import {parseArtistAliases, parseArtwork, parseURLs} from '#yaml'; import { sortAlbumsTracksChronologically, @@ -351,7 +351,7 @@ export class Artist extends Thing { fields: { 'Artist': {property: 'name'}, 'Directory': {property: 'directory'}, - 'URLs': {property: 'urls'}, + 'URLs': {property: 'urls', transform: parseURLs}, 'Context Notes': {property: 'contextNotes'}, // note: doesn't really work as an independent field yet diff --git a/src/data/things/MusicVideo.js b/src/data/things/MusicVideo.js index 77c8c619..dbb99a7f 100644 --- a/src/data/things/MusicVideo.js +++ b/src/data/things/MusicVideo.js @@ -4,9 +4,16 @@ import {colors} from '#cli'; import {input, V} from '#composite'; import {empty} from '#sugar'; import Thing from '#thing'; -import {is, isCuratedURL, isDate, isStringNonEmpty, validateArrayItems} - from '#validators'; -import {parseContributors, parseDate} from '#yaml'; +import {parseContributors, parseDate, parseURLs} from '#yaml'; + +import { + is, + isCuratedURL, + isCuratedURLEntry, + isDate, + isStringNonEmpty, + validateArrayItems, +} from '#validators'; import {constituteFrom} from '#composite/wiki-data'; @@ -66,6 +73,7 @@ export class MusicVideo extends Thing { constituteFrom('thing', V('date')), ], + // This is a string, not a {url, annotation} entry. url: { flags: {update: true, expose: true}, @@ -77,7 +85,7 @@ export class MusicVideo extends Thing { dependencies: ['_urls'], transform: (url, {'_urls': urls}) => (url ? url - : !empty(urls) ? urls[0] + : !empty(urls) ? urls[0].url : null), }, }, @@ -86,14 +94,14 @@ export class MusicVideo extends Thing { flags: {update: true, expose: true}, update: { - validate: validateArrayItems(isCuratedURL), + validate: validateArrayItems(isCuratedURLEntry), }, expose: { dependencies: ['_url'], transform: (urls, {'_url': url}) => - (url && urls ? [url, ...urls] - : url ? [url] + (url && urls ? [{url}, ...urls] + : url ? [{url}] : urls ? urls : []), }, @@ -142,8 +150,9 @@ export class MusicVideo extends Thing { 'Label': {property: 'label'}, 'Directory': {property: 'unqualifiedDirectory'}, 'Date': {property: 'date', transform: parseDate}, - 'URL': {property: 'url'}, - 'URLs': {property: 'urls'}, + + 'URL': {property: 'url'}, // Just a string, not an object + 'URLs': {property: 'urls', transform: parseURLs}, 'Cover Art File Extension': {property: 'coverArtFileExtension'}, 'Cover Art Dimensions': {property: 'coverArtDimensions'}, diff --git a/src/data/things/Track.js b/src/data/things/Track.js index 36e3733d..cb785211 100644 --- a/src/data/things/Track.js +++ b/src/data/things/Track.js @@ -35,6 +35,7 @@ import { parseDuration, parseLyrics, parseMusicVideos, + parseURLs, } from '#yaml'; import { @@ -1004,13 +1005,18 @@ export class Track extends Thing { transform: parseDuration, }, - 'Color': {property: 'color'}, + 'Color': { + property: 'color', + }, 'Needs Lyrics': { property: 'needsLyrics', }, - 'URLs': {property: 'urls'}, + 'URLs': { + property: 'urls', + transform: parseURLs, + }, // Artworks diff --git a/src/data/things/album/Album.js b/src/data/things/album/Album.js index 61420e52..1ae10ab1 100644 --- a/src/data/things/album/Album.js +++ b/src/data/things/album/Album.js @@ -17,6 +17,7 @@ import { parseDimensions, parseMusicVideos, parseWallpaperParts, + parseURLs, } from '#yaml'; import {withFlattenedList, withPropertyFromList} from '#composite/data'; @@ -651,7 +652,7 @@ export class Album extends Thing { 'Color': {property: 'color'}, - 'URLs': {property: 'urls'}, + 'URLs': {property: 'urls', transform: parseURLs}, // Artworks // (Note - this YAML section is deliberately ordered differently diff --git a/src/data/things/flash/Flash.js b/src/data/things/flash/Flash.js index b06b0452..588fbae5 100644 --- a/src/data/things/flash/Flash.js +++ b/src/data/things/flash/Flash.js @@ -12,6 +12,7 @@ import { parseCreditingSources, parseDate, parseDimensions, + parseURLs, } from '#yaml'; import {withPropertyFromObject} from '#composite/data'; @@ -216,7 +217,7 @@ export class Flash extends Thing { 'Directory': {property: 'directory'}, 'Page': {property: 'page'}, 'Color': {property: 'color'}, - 'URLs': {property: 'urls'}, + 'URLs': {property: 'urls', transform: parseURLs}, 'Date': { property: 'date', diff --git a/src/data/things/group/Group.js b/src/data/things/group/Group.js index f8dd413e..99ad633b 100644 --- a/src/data/things/group/Group.js +++ b/src/data/things/group/Group.js @@ -1,7 +1,7 @@ import {input, V} from '#composite'; import Thing from '#thing'; import {isBoolean} from '#validators'; -import {parseAnnotatedReferences, parseSerieses} from '#yaml'; +import {parseAnnotatedReferences, parseSerieses, parseURLs} from '#yaml'; import {withPropertyFromObject} from '#composite/data'; import {withUniqueReferencingThing} from '#composite/wiki-data'; @@ -176,7 +176,7 @@ export class Group extends Thing { }, 'Description': {property: 'description'}, - 'URLs': {property: 'urls'}, + 'URLs': {property: 'urls', transform: parseURLs}, 'Closely Linked Artists': { property: 'closelyLinkedArtists', diff --git a/src/data/yaml.js b/src/data/yaml.js index 58acb7c8..60017b3d 100644 --- a/src/data/yaml.js +++ b/src/data/yaml.js @@ -733,6 +733,26 @@ export function parseContributors(entries) { }); } +export function parseURLs(entries) { + return parseArrayEntries(entries, item => { + if (typeof item === 'object' && item['URL']) + return { + url: item['URL'], + annotation: item['Annotation'] ?? null, + }; + + if (typeof item !== 'string') return item; + + const match = item.match(extractAccentRegex); + if (!match) return item; + + return { + url: match.groups.main, + annotation: match.groups.accent, + }; + }); +} + export function parseAdditionalFiles(entries, {subdoc, AdditionalFile}) { return parseArrayEntries(entries, item => { if (typeof item !== 'object') return item; diff --git a/src/validators.js b/src/validators.js index 7dcd7b8c..2c3bd8e6 100644 --- a/src/validators.js +++ b/src/validators.js @@ -817,6 +817,24 @@ export function isCuratedURL(string) { return true; } +export const validateURLEntry = (isURL) => + validateProperties({ + url: isURL, + annotation: optional(isStringNonEmpty), + }); + +export const isURLEntry = + validateURLEntry(isURL); + +export const isCuratedURLEntry = + validateURLEntry(isCuratedURL); + +export const isURLList = + validateArrayItems(isURLEntry); + +export const isCuratedURLList = + validateArrayItems(isCuratedURLEntry); + export function validateReference(type) { return (ref) => { isStringNonEmpty(ref); |