From ba2751eae00c4bcf10403edbd549ca70dc316cab Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 21 Nov 2022 21:48:31 -0400 Subject: new "empty" sugar.js util --- src/data/yaml.js | 5 +-- src/listing-spec.js | 19 ++++++----- src/page/album.js | 94 +++++++++++++++++++++++++-------------------------- src/page/artist.js | 36 +++++++++++--------- src/page/flash.js | 7 ++-- src/page/group.js | 11 ++++-- src/page/homepage.js | 11 ++++-- src/page/listing.js | 4 ++- src/page/track.js | 44 ++++++++++++------------ src/util/sugar.js | 14 ++++++++ src/util/urls.js | 1 + src/util/wiki-data.js | 16 +++++---- 12 files changed, 150 insertions(+), 112 deletions(-) diff --git a/src/data/yaml.js b/src/data/yaml.js index 2c3c988..e18b733 100644 --- a/src/data/yaml.js +++ b/src/data/yaml.js @@ -31,6 +31,7 @@ import {color, ENABLE_COLOR, logInfo, logWarn} from '../util/cli.js'; import { decorateErrorWithIndex, + empty, mapAggregate, openAggregate, showAggregate, @@ -143,7 +144,7 @@ function makeProcessDocument( .map(([field]) => field) .filter((field) => !knownFields.includes(field)); - if (unknownFields.length) { + if (!empty(unknownFields)) { throw new makeProcessDocument.UnknownFieldsError(unknownFields); } @@ -1253,7 +1254,7 @@ export function filterDuplicateDirectories(wikiData) { directoryPlaces[directory] = [thing]; } } - if (!duplicateDirectories.length) return; + if (empty(duplicateDirectories)) return; duplicateDirectories.sort((a, b) => { const aL = a.toLowerCase(); const bL = b.toLowerCase(); diff --git a/src/listing-spec.js b/src/listing-spec.js index 82706be..9924474 100644 --- a/src/listing-spec.js +++ b/src/listing-spec.js @@ -1,6 +1,7 @@ /** @format */ import { + empty, accumulateSum, } from './util/sugar.js'; @@ -264,7 +265,7 @@ const listingSpec = [ }}) { const processContribs = values => { const filteredValues = values - .filter(value => value.date && value.contribs.length); + .filter(value => value.date && !empty(value.contribs)); const datedArtistLists = sortByDate(filteredValues) .map(({ @@ -447,15 +448,15 @@ const listingSpec = [ data.flatMap(({category, groups}) => [ html.tag('dt', language.$('listingPage.listGroups.byCategory.category', { - category: groups.length - ? link.groupInfo(groups[0], { + category: empty(groups) + ? category.name + : link.groupInfo(groups[0], { text: category.name, - }) - : category.name, + }), })), html.tag('dd', - groups.length === 0 + empty(groups) ? null // todo: #85 : html.tag('ul', category.groups.map(group => @@ -549,7 +550,7 @@ const listingSpec = [ groupData .map(group => { const albums = group.albums.filter(a => a.date); - return albums.length && { + return !empty(albums) && { group, directory: group.directory, name: group.name, @@ -736,7 +737,7 @@ const listingSpec = [ data: ({wikiData: {trackData}}) => chunkByProperties( - trackData.filter(t => t.featuredInFlashes?.length > 0), + trackData.filter(t => !empty(t.featuredInFlashes)), ['album']), html: (data, {html, language, link}) => @@ -804,7 +805,7 @@ const listingSpec = [ album, tracks: album.tracks.filter(t => t.lyrics), })) - .filter(({tracks}) => tracks.length), + .filter(({tracks}) => !empty(tracks)), html: (data, {html, language, link}) => html.tag('dl', diff --git a/src/page/album.js b/src/page/album.js index 1313bb3..14d4a9d 100644 --- a/src/page/album.js +++ b/src/page/album.js @@ -2,7 +2,11 @@ // Album page specification. -import {bindOpts, compareArrays} from '../util/sugar.js'; +import { + bindOpts, + compareArrays, + empty, +} from '../util/sugar.js'; import { getAlbumCover, @@ -45,8 +49,8 @@ export function write(album, {wikiData}) { }; const hasCommentaryEntries = - [album, ...album.tracks].filter((x) => x.commentary).length > 0; - const hasAdditionalFiles = album.additionalFiles?.length > 0; + !empty([album, ...album.tracks].filter((x) => x.commentary)); + const hasAdditionalFiles = !empty(album.additionalFiles); const albumDuration = getTotalDuration(album.tracks); const displayTrackGroups = @@ -132,7 +136,7 @@ export function write(album, {wikiData}) { `--album-directory: ${album.directory}`, ]), - banner: album.bannerArtistContribs.length && { + banner: !empty(album.bannerArtistContribs) && { dimensions: album.bannerDimensions, path: [ 'media.albumBanner', @@ -161,7 +165,7 @@ export function write(album, {wikiData}) { [html.joinChildren]: '
', }, [ - album.artistContribs.length && + !empty(album.artistContribs) && language.$('releaseInfo.by', { artists: getArtistString(album.artistContribs, { showContrib: true, @@ -169,7 +173,7 @@ export function write(album, {wikiData}) { }), }), - album.coverArtistContribs.length && + !empty(album.coverArtistContribs) && language.$('releaseInfo.coverArtBy', { artists: getArtistString(album.coverArtistContribs, { showContrib: true, @@ -177,7 +181,7 @@ export function write(album, {wikiData}) { }), }), - album.wallpaperArtistContribs.length && + !empty(album.wallpaperArtistContribs) && language.$('releaseInfo.wallpaperArtBy', { artists: getArtistString(album.wallpaperArtistContribs, { showContrib: true, @@ -185,7 +189,7 @@ export function write(album, {wikiData}) { }), }), - album.bannerArtistContribs.length && + !empty(album.bannerArtistContribs) && language.$('releaseInfo.bannerArtBy', { artists: getArtistString(album.bannerArtistContribs, { showContrib: true, @@ -204,7 +208,7 @@ export function write(album, {wikiData}) { date: language.formatDate(album.coverArtDate), }), - album.duration && + album.duration > 0 && language.$('releaseInfo.duration', { duration: language.formatDuration(albumDuration, { approximate: album.tracks.length > 1, @@ -229,7 +233,7 @@ export function write(album, {wikiData}) { }), ]), - album.urls?.length && + !empty(album.urls) && html.tag('p', language.$('releaseInfo.listenOn', { links: language.formatDisjunctionList( @@ -434,7 +438,7 @@ export function generateAlbumSidebar(album, currentTrack, { isAlbumPage && transformMultiline(group.descriptionShort), - group.urls?.length && + !empty(group.urls) && html.tag('p', language.$('releaseInfo.visitOn', { links: language.formatDisjunctionList( group.urls.map((url) => fancifyURL(url)) @@ -459,24 +463,16 @@ export function generateAlbumSidebar(album, currentTrack, { ]), ]); - if (groupParts.length) { - if (isTrackPage) { - const combinedGroupPart = - groupParts - .map(groupPart => groupPart.filter(Boolean).join('\n')) - .join('\n
\n'); - return { - multiple: [trackListPart, combinedGroupPart], - }; - } else { - return { - multiple: [...groupParts, trackListPart], - }; - } + if (empty(groupParts)) { + return {content: trackListPart}; + } else if (isTrackPage) { + const combinedGroupPart = + groupParts + .map(groupPart => groupPart.filter(Boolean).join('\n')) + .join('\n
\n'); + return {multiple: [trackListPart, combinedGroupPart]}; } else { - return { - content: trackListPart, - }; + return {multiple: [...groupParts, trackListPart]}; } } @@ -490,7 +486,7 @@ export function generateAlbumSecondaryNav(album, currentTrack, { const {groups} = album; - if (!groups.length) { + if (empty(groups)) { return null; } @@ -503,27 +499,29 @@ export function generateAlbumSecondaryNav(album, currentTrack, { return {group, next, previous}; }) .map(({group, next, previous}) => { - const previousNext = + const previousLink = isAlbumPage && - [ - previous && - link.album(previous, { - color: false, - text: language.$('misc.nav.previous'), - }), - next && - link.album(next, { - color: false, - text: language.$('misc.nav.next'), - }), - ].filter(Boolean); + previous && + link.album(previous, { + color: false, + text: language.$('misc.nav.previous'), + }); + const nextLink = + isAlbumPage && + next && + link.album(next, { + color: false, + text: language.$('misc.nav.next'), + }); + const links = [previousLink, nextLink].filter(Boolean); return html.tag('span', - {style: getLinkThemeString(group.color)}, [ - language.$('albumSidebar.groupBox.title', { - group: link.groupInfo(group), - }), - previousNext?.length && `(${previousNext.join(',\n')})`, - ]); + {style: getLinkThemeString(group.color)}, + [ + language.$('albumSidebar.groupBox.title', { + group: link.groupInfo(group), + }), + !empty(links) && `(${language.formatUnitList(links)})`, + ]); }); return { diff --git a/src/page/artist.js b/src/page/artist.js index 8606a7a..efd4e1f 100644 --- a/src/page/artist.js +++ b/src/page/artist.js @@ -4,7 +4,11 @@ // // NB: See artist-alias.js for artist alias redirect pages. -import {bindOpts, unique} from '../util/sugar.js'; +import { + bindOpts, + empty, + unique, +} from '../util/sugar.js'; import { chunkByProperties, @@ -43,7 +47,7 @@ export function write(artist, {wikiData}) { ...(artist.tracksAsCommentator ?? []), ]); - const hasGallery = artThingsGallery.length > 0; + const hasGallery = !empty(artThingsGallery); const getArtistsAndContrib = (thing, key) => ({ artists: thing[key]?.filter(({who}) => who !== artist), @@ -155,7 +159,7 @@ export function write(artist, {wikiData}) { }) => original ? language.$('artistPage.creditList.entry.rerelease', {entry}) - : artists.length + : !empty(artists) ? contrib.what || contrib.whatArray?.length ? language.$( 'artistPage.creditList.entry.withArtists.withContribution', @@ -250,7 +254,7 @@ export function write(artist, {wikiData}) { const ret = {}; ret.link = serializeLink(thing); if (contrib.what) ret.contribution = contrib.what; - if (artists.length) ret.otherArtists = serializeContribs(artists); + if (!empty(artists)) ret.otherArtists = serializeContribs(artists); return ret; }; @@ -266,10 +270,10 @@ export function write(artist, {wikiData}) { })); const jumpTo = { - tracks: allTracks.length > 0, - art: artThingsAll.length > 0, - flashes: wikiInfo.enableFlashesAndGames && flashes.length > 0, - commentary: commentaryThings.length > 0, + tracks: !empty(allTracks), + art: !empty(artThingsAll), + flashes: wikiInfo.enableFlashesAndGames && !empty(flashes), + commentary: !empty(commentaryThings), }; const showJumpTo = Object.values(jumpTo).includes(true); @@ -378,7 +382,7 @@ export function write(artist, {wikiData}) { html.tag('hr'), ]), - urls?.length && + !empty(urls) && html.tag('p', language.$('releaseInfo.visitOn', { links: language.formatDisjunctionList( @@ -422,12 +426,12 @@ export function write(artist, {wikiData}) { })), ...html.fragment( - allTracks.length && [ + !empty(allTracks) && [ html.tag('h2', {id: 'tracks'}, language.$('artistPage.trackList.title')), - totalDuration && + totalDuration > 0 && html.tag('p', language.$('artistPage.contributedDurationLine', { artist: artist.name, @@ -440,7 +444,7 @@ export function write(artist, {wikiData}) { ), })), - musicGroups.length && + !empty(musicGroups) && html.tag('p', language.$('artistPage.musicGroupsLine', { groups: language.formatUnitList( @@ -460,7 +464,7 @@ export function write(artist, {wikiData}) { ]), ...html.fragment( - artThingsAll.length && [ + !empty(artThingsAll) && [ html.tag('h2', {id: 'art'}, language.$('artistPage.artList.title')), @@ -473,7 +477,7 @@ export function write(artist, {wikiData}) { }) })), - artGroups.length && + !empty(artGroups) && html.tag('p', language.$('artistPage.artGroupsLine', { groups: language.formatUnitList( @@ -527,7 +531,7 @@ export function write(artist, {wikiData}) { ...html.fragment( wikiInfo.enableFlashesAndGames && - flashes.length && [ + !empty(flashes) && [ html.tag('h2', {id: 'flashes'}, language.$('artistPage.flashList.title')), @@ -569,7 +573,7 @@ export function write(artist, {wikiData}) { ]), ...html.fragment( - commentaryThings.length && [ + !empty(commentaryThings) && [ html.tag('h2', {id: 'commentary'}, language.$('artistPage.commentaryList.title')), diff --git a/src/page/flash.js b/src/page/flash.js index ad61997..237dd47 100644 --- a/src/page/flash.js +++ b/src/page/flash.js @@ -2,6 +2,7 @@ // Flash page and index specifications. +import {empty} from '../util/sugar.js'; import {getFlashLink} from '../util/wiki-data.js'; export function condition({wikiData}) { @@ -50,7 +51,7 @@ export function write(flash, {wikiData}) { date: language.formatDate(flash.date), })), - (flash.page || flash.urls?.length) && + (flash.page || !empty(flash.urls)) && html.tag('p', language.$('releaseInfo.playOn', { links: language.formatDisjunctionList( @@ -62,7 +63,7 @@ export function write(flash, {wikiData}) { })), ...html.fragment( - flash.featuredTracks?.length && [ + !empty(flash.featuredTracks) && [ html.tag('p', `Tracks featured in ${ flash.name.replace(/\.$/, '') @@ -81,7 +82,7 @@ export function write(flash, {wikiData}) { ]), ...html.fragment( - flash.contributorContribs.length && [ + !empty(flash.contributorContribs) && [ html.tag('p', language.$('releaseInfo.contributors')), diff --git a/src/page/group.js b/src/page/group.js index 0ff04ae..2bd6da9 100644 --- a/src/page/group.js +++ b/src/page/group.js @@ -2,7 +2,14 @@ // Group page specifications. -import {getTotalDuration, sortChronologically} from '../util/wiki-data.js'; +import { + empty, +} from '../util/sugar.js'; + +import { + getTotalDuration, + sortChronologically, +} from '../util/wiki-data.js'; export function targets({wikiData}) { return wikiData.groupData; @@ -44,7 +51,7 @@ export function write(group, {wikiData}) { group: group.name })), - group.urls?.length && + !empty(group.urls) && html.tag('p', language.$('releaseInfo.visitOn', { links: language.formatDisjunctionList( diff --git a/src/page/homepage.js b/src/page/homepage.js index 2219593..c15c969 100644 --- a/src/page/homepage.js +++ b/src/page/homepage.js @@ -1,6 +1,11 @@ // Homepage specification. -import {getNewAdditions, getNewReleases} from '../util/wiki-data.js'; +import {empty} from '../util/sugar.js'; + +import { + getNewAdditions, + getNewReleases, +} from '../util/wiki-data.js'; export function writeTargetless({wikiData}) { const {newsData, staticPageData, homepageLayout, wikiInfo} = wikiData; @@ -29,7 +34,7 @@ export function writeTargetless({wikiData}) { : []; } - if (row.sourceAlbums.length) { + if (!empty(row.sourceAlbums)) { entry.gridEntries.push(...row.sourceAlbums.map(album => ({item: album}))); } @@ -86,7 +91,7 @@ export function writeTargetless({wikiData}) { lazy: i > 0, })), - entry.actionLinks.length && + !empty(entry.actionLinks) && html.tag('div', {class: 'grid-actions'}, entry.actionLinks.map(action => transformInline(action) diff --git a/src/page/listing.js b/src/page/listing.js index 5a2b6d2..65982f8 100644 --- a/src/page/listing.js +++ b/src/page/listing.js @@ -10,6 +10,8 @@ // Individual listing specs are described in src/listing-spec.js, but are // provided via wikiData like other (normal) data objects. +import {empty} from '../util/sugar.js'; + import {getTotalDuration} from '../util/wiki-data.js'; export function condition({wikiData}) { @@ -201,7 +203,7 @@ function generateLinkIndexForListings(currentListing, forSidebar, { ...rest, listings: listings.filter(({condition: c}) => !c || c({wikiData})), })) - .filter(({listings}) => listings.length > 0); + .filter(({listings}) => !empty(listings)); const genUL = (listings) => html.tag('ul', diff --git a/src/page/track.js b/src/page/track.js index bdbe60c..cf93724 100644 --- a/src/page/track.js +++ b/src/page/track.js @@ -9,7 +9,10 @@ import { generateAlbumSidebar, } from './album.js'; -import {bindOpts} from '../util/sugar.js'; +import { + bindOpts, + empty, +} from '../util/sugar.js'; import { getTrackCover, @@ -115,8 +118,8 @@ export function write(track, {wikiData}) { getArtistString: _getArtistString, language, }) => { - const hasArtists = track.artistContribs?.length > 0; - const hasCoverArtists = track.coverArtistContribs?.length > 0; + const hasArtists = !empty(track.artistContribs); + const hasCoverArtists = !empty(track.coverArtistContribs); const getArtistString = (contribs) => _getArtistString(contribs, { // We don't want to put actual HTML tags in social embeds (sadly @@ -197,7 +200,7 @@ export function write(track, {wikiData}) { // disabled for now! shifting banner position per height of page is disorienting /* - banner: album.bannerArtistContribs.length && { + banner: !empty(album.bannerArtistContribs) && { classes: ['dim'], dimensions: album.bannerDimensions, path: ['media.albumBanner', album.directory, album.bannerFileExtension], @@ -222,7 +225,7 @@ export function write(track, {wikiData}) { [html.joinChildren]: '
', }, [ - track.artistContribs.length && + !empty(track.artistContribs) && language.$('releaseInfo.by', { artists: getArtistString(track.artistContribs, { showContrib: true, @@ -230,15 +233,12 @@ export function write(track, {wikiData}) { }), }), - track.coverArtistContribs.length && + !empty(track.coverArtistContribs) && language.$('releaseInfo.coverArtBy', { - artists: getArtistString( - track.coverArtistContribs, - { - showContrib: true, - showIcons: true, - } - ), + artists: getArtistString(track.coverArtistContribs, { + showContrib: true, + showIcons: true, + }), }), track.date && @@ -261,15 +261,15 @@ export function write(track, {wikiData}) { ]), html.tag('p', - (track.urls?.length - ? language.$('releaseInfo.listenOn', { + (empty(track.urls) + ? language.$('releaseInfo.listenOn.noLinks') + : language.$('releaseInfo.listenOn', { links: language.formatDisjunctionList( track.urls.map(url => fancifyURL(url, {language}))), - }) - : language.$('releaseInfo.listenOn.noLinks'))), + }))), ...html.fragment( - otherReleases.length && [ + !empty(otherReleases) && [ html.tag('p', language.$('releaseInfo.alsoReleasedAs')), html.tag('ul', otherReleases.map(track => html.tag('li', language.$('releaseInfo.alsoReleasedAs.item', { @@ -279,7 +279,7 @@ export function write(track, {wikiData}) { ]), ...html.fragment( - track.contributorContribs.length && [ + !empty(track.contributorContribs) && [ html.tag('p', language.$('releaseInfo.contributors')), html.tag('ul', track.contributorContribs.map(contrib => html.tag('li', getArtistString([contrib], { @@ -289,7 +289,7 @@ export function write(track, {wikiData}) { ]), ...html.fragment( - referencedTracks.length && [ + !empty(referencedTracks) && [ html.tag('p', language.$('releaseInfo.tracksReferenced', { track: html.tag('i', track.name), })), @@ -297,7 +297,7 @@ export function write(track, {wikiData}) { ]), ...html.fragment( - referencedByTracks.length && [ + !empty(referencedByTracks) && [ html.tag('p', language.$('releaseInfo.tracksThatReference', { track: html.tag('i', track.name), })), @@ -309,7 +309,7 @@ export function write(track, {wikiData}) { ...html.fragment( wikiInfo.enableFlashesAndGames && - flashesThatFeature.length && [ + !empty(flashesThatFeature) && [ html.tag('p', language.$('releaseInfo.flashesThatFeature', { track: `${track.name}`, })), diff --git a/src/util/sugar.js b/src/util/sugar.js index c836d0c..24ae863 100644 --- a/src/util/sugar.js +++ b/src/util/sugar.js @@ -30,6 +30,20 @@ export function* splitArray(array, fn) { } } +// Null-accepting function to check if an array is empty. Accepts null (and +// treats as empty) as a shorthand for "hey, check if this property is an array +// with/without stuff in it" for objects where properties that are PRESENT but +// don't currently have a VALUE are null (instead of undefined). +export function empty(arrayOrNull) { + if (arrayOrNull === null) { + return true; + } else if (Array.isArray(arrayOrNull)) { + return arrayOrNull.length === 0; + } else { + throw new Error(`Expected array or null`); + } +} + // Sums the values in an array, optionally taking a function which maps each // item to a number (handy for accessing a certain property on an array of like // objects). This also coalesces null values to zero, so if the mapping function diff --git a/src/util/urls.js b/src/util/urls.js index 45ec4c8..d86c047 100644 --- a/src/util/urls.js +++ b/src/util/urls.js @@ -11,6 +11,7 @@ // the domain of link.js. import * as path from 'path'; + import {withEntries} from './sugar.js'; export function generateURLs(urlSpec) { diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js index 97ffab7..b0b0b2e 100644 --- a/src/util/wiki-data.js +++ b/src/util/wiki-data.js @@ -2,6 +2,8 @@ // Utility functions for interacting with wiki data. +import {empty} from './sugar.js'; + // Generic value operations export function getKebabCase(name) { @@ -16,9 +18,11 @@ export function getKebabCase(name) { } export function chunkByConditions(array, conditions) { - if (array.length === 0) { + if (empty(array)) { return []; - } else if (conditions.length === 0) { + } + + if (empty(conditions)) { return [array]; } @@ -469,7 +473,7 @@ export function getNewAdditions(numAlbums, {wikiData}) { // Then cycle over that sorted array, adding one al8um from each to // the main array until we've run out or have met the target num8er // of al8ums. - while (groupArray.length) { + while (!empty(groupArray)) { let j = 0; while (j < groupArray.length) { const entry = groupArray[j]; @@ -485,10 +489,10 @@ export function getNewAdditions(numAlbums, {wikiData}) { break outerLoop; } - if (entry.length) { - j++; - } else { + if (empty(entry)) { groupArray.splice(j, 1); + } else { + j++; } } } -- cgit 1.3.0-6-gf8a5