From 2b6e7d3d9950aad31536d63a835869502a70af46 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Mon, 25 Jan 2021 17:27:05 -0400 Subject: initial staging commit (data/media pruned) --- upd8.js | 1250 ++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 828 insertions(+), 422 deletions(-) (limited to 'upd8.js') diff --git a/upd8.js b/upd8.js index dac8a13..bcb9533 100644 --- a/upd8.js +++ b/upd8.js @@ -1,3 +1,5 @@ +#!/usr/bin/env node + // HEY N8RDS! // // This is one of the 8ACKEND FILES. It's not used anywhere on the actual site @@ -104,6 +106,7 @@ const { cacheOneArg, curry, decorateTime, + filterEmptyLines, joinNoOxford, mapInPlace, parseOptions, @@ -116,36 +119,16 @@ const { const C = require('./common/common'); -const CACHEBUST = 1; - -const SITE_CANONICAL_BASE = 'https://hsmusic.wiki/'; -const SITE_TITLE = 'Homestuck Music Wiki'; -const SITE_SHORT_TITLE = 'HSMusic'; -const SITE_DESCRIPTION = `Expansive resource for anyone interested in fan-made and official Homestuck music alike; an archive for all things related.`; - -const SITE_DONATE_LINK = 'https://liberapay.com/nebula'; - -function readDataFile(file) { - // fight me bro - return fs.readFileSync(path.join(C.DATA_DIRECTORY, file)).toString().trim(); -} - -const SITE_ABOUT = readDataFile('about.html'); -const SITE_CHANGELOG = readDataFile('changelog.html'); -const SITE_DISCORD = readDataFile('discord.html'); -const SITE_DONATE = readDataFile('donate.html'); -const SITE_FEEDBACK = readDataFile('feedback.html'); -const SITE_JS_DISABLED = readDataFile('js-disabled.html'); - -// Might ena8le this later... we'll see! Eventually. May8e. -const ENABLE_ARTIST_AVATARS = false; -const ARTIST_AVATAR_DIRECTORY = 'artist-avatar'; +const CACHEBUST = 2; +const WIKI_INFO_FILE = 'wiki-info.txt'; +const HOMEPAGE_INFO_FILE = 'homepage.txt'; const ARTIST_DATA_FILE = 'artists.txt'; const FLASH_DATA_FILE = 'flashes.txt'; const NEWS_DATA_FILE = 'news.txt'; const TAG_DATA_FILE = 'tags.txt'; const GROUP_DATA_FILE = 'groups.txt'; +const STATIC_PAGE_DATA_FILE = 'static-pages.txt'; const CSS_FILE = 'site.css'; @@ -155,12 +138,19 @@ const CSS_FILE = 'site.css'; // // Upd8: Okay yeah these aren't actually any different. Still cleaner than // passing around a data object containing all this, though. +let dataPath; +let mediaPath; +let outputPath; + +let wikiInfo; +let homepageInfo; let albumData; let trackData; let flashData; let newsData; let tagData; let groupData; +let staticPageData; let artistNames; let artistData; @@ -180,9 +170,9 @@ let queueSize; // only the track listing, not track data itself), and dealing with errors of // missing track files (or track files which are not linked to al8ums). All a // 8unch of stuff that's a pain to deal with for no apparent 8enefit. -async function findAlbumDataFiles() { - return (await readdir(path.join(C.DATA_DIRECTORY, C.DATA_ALBUM_DIRECTORY))) - .map(albumFile => path.join(C.DATA_DIRECTORY, C.DATA_ALBUM_DIRECTORY, albumFile)); +async function findAlbumDataFiles(albumDirectory) { + return (await readdir(path.join(albumDirectory))) + .map(albumFile => path.join(albumDirectory, albumFile)); } function* getSections(lines) { @@ -194,7 +184,23 @@ function* getSections(lines) { function getBasicField(lines, name) { const line = lines.find(line => line.startsWith(name + ':')); return line && line.slice(name.length + 1).trim(); -}; +} + +function getBooleanField(lines, name) { + // The ?? oper8tor (which is just, hilariously named, lol) can 8e used to + // specify a default! + const value = getBasicField(lines, name); + switch (value) { + case 'yes': + case 'true': + return true; + case 'no': + case 'false': + return false; + default: + return null; + } +} function getListField(lines, name) { let startIndex = lines.findIndex(line => line.startsWith(name + ':')); @@ -268,7 +274,7 @@ function getMultilineField(lines, name) { return null; } startIndex++; - let endIndex = lines.findIndex((line, index) => index >= startIndex && !line.startsWith(' ')); + let endIndex = lines.findIndex((line, index) => index >= startIndex && line.length && !line.startsWith(' ')); if (endIndex === -1) { endIndex = lines.length; } @@ -422,7 +428,7 @@ function parseAttributes(string) { function transformMultiline(text, treatAsDocument=false) { // Heck yes, HTML magics. - text = transformInline(text); + text = transformInline(text.trim()); if (treatAsDocument) { return text; @@ -430,26 +436,138 @@ function transformMultiline(text, treatAsDocument=false) { const outLines = []; - let inList = false; + const indentString = ' '.repeat(4); + + let levelIndents = []; + const openLevel = indent => { + // opening a sublist is a pain: to be semantically *and* visually + // correct, we have to append the
-

Art & Flash Contributors

+

Art${wikiInfo.features.flashesAndGames ? ` & Flash` : ''} Contributors

-

Art & Flash Contributors

+

Art${wikiInfo.features.flashesAndGames ? ` & Flash` : ''} Contributors

`], + wikiInfo.features.groupUI && [['groups', 'by-name'], `Groups - by Name`, groupData .filter(x => x.isGroup) .sort(sortByName) .map(group => fixWS`
  • ${group.name}
  • `)], + wikiInfo.features.groupUI && [['groups', 'by-category'], `Groups - by Category`, fixWS`
    ${groupData.filter(x => x.isCategory).map(category => fixWS` @@ -2488,6 +2790,7 @@ function writeListingPages() { `).join('\n')}
    `], + wikiInfo.features.groupUI && [['groups', 'by-albums'], `Groups - by Albums`, groupData .filter(x => x.isGroup) .map(group => ({group, albums: group.albums.length})) @@ -2495,6 +2798,7 @@ function writeListingPages() { .map(({ group, albums }) => fixWS`
  • ${group.name} (${s(albums, 'album')})
  • `)], + wikiInfo.features.groupUI && [['groups', 'by-tracks'], `Groups - by Tracks`, groupData .filter(x => x.isGroup) .map(group => ({group, tracks: group.albums.reduce((acc, album) => acc + album.tracks.length, 0)})) @@ -2502,6 +2806,7 @@ function writeListingPages() { .map(({ group, tracks }) => fixWS`
  • ${group.name} (${s(tracks, 'track')})
  • `)], + wikiInfo.features.groupUI && [['groups', 'by-duration'], `Groups - by Duration`, groupData .filter(x => x.isGroup) .map(group => ({group, duration: getTotalDuration(group.albums.flatMap(album => album.tracks))})) @@ -2509,6 +2814,7 @@ function writeListingPages() { .map(({ group, duration }) => fixWS`
  • ${group.name} (${getDurationString(duration)})
  • `)], + wikiInfo.features.groupUI && [['groups', 'by-latest'], `Groups - by Latest Album`, C.sortByDate(groupData .filter(x => x.isGroup) .map(group => ({group, date: group.albums[group.albums.length - 1].date})) @@ -2580,9 +2886,11 @@ function writeListingPages() { (${s(track.referencedBy.length, 'time')} referenced) `)], + wikiInfo.features.flashesAndGames && [['tracks', 'in-flashes', 'by-album'], `Tracks - in Flashes & Games (by Album)`, albumChunkedList( C.sortByDate(trackData.slice()).filter(track => track.album.directory !== C.UNRELEASED_TRACKS_DIRECTORY && track.flashes.length > 0), track => `
  • ${track.name}
  • `)], + wikiInfo.features.flashesAndGames && [['tracks', 'in-flashes', 'by-flash'], `Tracks - in Flashes & Games (by Flash)`, fixWS`
    ${C.sortByDate(flashData.filter(flash => !flash.act8r8k)) @@ -2606,15 +2914,17 @@ function writeListingPages() { track => fixWS`
  • ${track.name}
  • `)], + wikiInfo.features.artTagUI && [['tags', 'by-name'], 'Tags - by Name', tagData.slice().sort(sortByName) .filter(tag => !tag.isCW) .map(tag => `
  • ${tag.name}
  • `)], + wikiInfo.features.artTagUI && [['tags', 'by-uses'], 'Tags - by Uses', tagData.slice().sort(sortByName) .filter(tag => !tag.isCW) .map(tag => ({tag, timesUsed: tag.things.length})) .sort((a, b) => b.timesUsed - a.timesUsed) .map(({ tag, timesUsed }) => `
  • ${tag.name} (${s(timesUsed, 'time')})
  • `)] - ]; + ].filter(Boolean); const getWordCount = str => { const wordCount = str.split(' ').length; @@ -2631,20 +2941,20 @@ function writeListingPages() { main: { content: fixWS`

    Listings

    -

    ${SITE_TITLE}: ${releasedTracks.length} tracks across ${releasedAlbums.length} albums, totaling ~${getDurationString(getTotalDuration(releasedTracks))} ${getTotalDuration(releasedTracks) > 3600 ? 'hours' : 'minutes'}.

    +

    ${wikiInfo.name}: ${releasedTracks.length} tracks across ${releasedAlbums.length} albums, totaling ~${getDurationString(getTotalDuration(releasedTracks))} ${getTotalDuration(releasedTracks) > 3600 ? 'hours' : 'minutes'}.


    Feel free to explore any of the listings linked below and in the sidebar!

    ${generateLinkIndexForListings(listingDescriptors)} ` }, - sidebar: { + sidebarLeft: { content: generateSidebarForListings(listingDescriptors) }, nav: { links: [ - ['./', SITE_SHORT_TITLE], + ['./', wikiInfo.shortName], [`${C.LISTINGS_DIRECTORY}/`, 'Listings'] ] } @@ -2684,26 +2994,26 @@ function writeListingPages() {
    ${transformMultiline(album.commentary)}
    - ` || ``} + `} ${tracks.filter(t => t.commentary).map(track => fixWS`

    ${track.name}

    ${transformMultiline(track.commentary)}
    - `).join('\n') || ``} + `).join('\n')} `) .join('\n') } ` }, - sidebar: { + sidebarLeft: { content: generateSidebarForListings(listingDescriptors, 'all-commentary') }, nav: { links: [ - ['./', SITE_SHORT_TITLE], + ['./', wikiInfo.shortName], [`${C.LISTING_DIRECTORY}/`, 'Listings'], [`${C.LISTING_DIRECTORY}/all-commentary`, 'All Commentary'] ] @@ -2742,13 +3052,13 @@ function writeListingPages() { ` }, - sidebar: { + sidebarLeft: { content: generateSidebarForListings(listingDescriptors, 'all-commentary') }, nav: { links: [ - ['./', SITE_SHORT_TITLE], + ['./', wikiInfo.shortName], [`${C.LISTING_DIRECTORY}/`, 'Listings'], [`${C.LISTING_DIRECTORY}/random`, 'Random Pages'] ] @@ -2774,13 +3084,13 @@ function writeListingPage(directoryParts, title, items, listingDescriptors) { ` }, - sidebar: { + sidebarLeft: { content: generateSidebarForListings(listingDescriptors, directoryParts) }, nav: { links: [ - ['./', SITE_SHORT_TITLE], + ['./', wikiInfo.shortName], [`${C.LISTING_DIRECTORY}/`, 'Listings'], [`${C.LISTING_DIRECTORY}/${directoryParts.join('/')}/`, title] ] @@ -2814,6 +3124,10 @@ function generateLinkIndexForListings(listingDescriptors, currentDirectoryParts) } function writeTagPages() { + if (!wikiInfo.features.artTagUI) { + return; + } + return progressPromiseAll(`Writing tag pages.`, queue(tagData .filter(tag => !tag.isCW) .map(curry(writeTagPage)), queueSize)); @@ -2850,8 +3164,8 @@ function writeTagPage(tag) { nav: { links: [ - ['./', SITE_SHORT_TITLE], - [`${C.LISTING_DIRECTORY}/`, 'Listings'], + ['./', wikiInfo.shortName], + wikiInfo.features.listings && [`${C.LISTING_DIRECTORY}/`, 'Listings'], [null, 'Tag:'], [`${C.TAG_DIRECTORY}/${tag.directory}/`, tag.name] ] @@ -2962,7 +3276,7 @@ function getLinkedArtist(ref) { function getLinkedFlash(ref) { if (!ref) return null; ref = ref.replace('flash:', ''); - return flashData.find(flash => flash.directory === ref); + return flashData?.find(flash => flash.directory === ref); } function getLinkedTag(ref) { @@ -3143,7 +3457,7 @@ function chronologyLinks(currentTrack, { return fixWS`
    ${heading} - ${parts.length && `(${parts.join(', ')})` || ``} + ${parts.length && `(${parts.join(', ')})`}
    `; }).filter(Boolean).join('\n'); @@ -3231,6 +3545,10 @@ function generateSidebarForAlbum(album, currentTrack = null) { } function generateSidebarRightForAlbum(album, currentTrack = null) { + if (!wikiInfo.features.groupUI) { + return null; + } + const { groups } = album; if (groups.length) { return { @@ -3254,25 +3572,31 @@ function generateSidebarRightForAlbum(album, currentTrack = null) { } function generateSidebarForGroup(isGallery = false, currentGroup = null) { - return ` -

    Groups

    -
    - ${groupData.filter(x => x.isCategory).map(category => [ - fixWS` -
    - ${category.name} -
    -
      - ${category.groups.map(group => fixWS` -
    • - ${group.name} -
    • - `).join('\n')} -
    - ` - ]).join('\n')} -
    - `; + if (!wikiInfo.features.groupUI) { + return null; + } + + return { + content: fixWS` +

    Groups

    +
    + ${groupData.filter(x => x.isCategory).map(category => [ + fixWS` +
    + ${category.name} +
    +
      + ${category.groups.map(group => fixWS` +
    • + ${group.name} +
    • + `).join('\n')} +
    + ` + ]).join('\n')} +
    + ` + }; } function writeGroupPages() { @@ -3321,13 +3645,11 @@ async function writeGroupPage(group) { ` }, - sidebar: { - content: generateSidebarForGroup(false, group) - }, - nav: { + sidebarLeft: generateSidebarForGroup(false, group), + nav: (wikiInfo.features.groupUI ? { links: [ - ['./', SITE_SHORT_TITLE], - [`${C.LISTING_DIRECTORY}/`, 'Listings'], + ['./', wikiInfo.shortName], + wikiInfo.features.listings && [`${C.LISTING_DIRECTORY}/`, 'Listings'], [null, 'Group:'], [`${C.GROUP_DIRECTORY}/${group.directory}/`, group.name], [null, `(${[ @@ -3335,7 +3657,7 @@ async function writeGroupPage(group) { `Gallery` ].join(', ') + (npInfo.length ? '; ' + npInfo : '')})`] ] - } + } : {simple: true}) }); await writePage([C.GROUP_DIRECTORY, group.directory, 'gallery'], { @@ -3348,7 +3670,7 @@ async function writeGroupPage(group) { content: fixWS`

    ${group.name} - Gallery

    ${releasedTracks.length} track${releasedTracks.length === 1 ? '' : 's'} across ${releasedAlbums.length} album${releasedAlbums.length === 1 ? '' : 's'}, totaling ~${getDurationString(totalDuration)} ${totalDuration > 3600 ? 'hours' : 'minutes'}.

    -

    (Choose another group to filter by!)

    + ${wikiInfo.features.groupUI && wikiInfo.features.listings && `

    (Choose another group to filter by!)

    `}
    ${getGridHTML({ entries: C.sortByDate(group.albums.map(item => ({item}))).reverse(), @@ -3359,13 +3681,11 @@ async function writeGroupPage(group) {
    ` }, - sidebar: { - content: generateSidebarForGroup(true, group) - }, - nav: { + sidebarLeft: generateSidebarForGroup(true, group), + nav: (wikiInfo.features.groupUI ? { links: [ - ['./', SITE_SHORT_TITLE], - [`${C.LISTING_DIRECTORY}/`, 'Listings'], + ['./', wikiInfo.shortName], + wikiInfo.features.listings && [`${C.LISTING_DIRECTORY}/`, 'Listings'], [null, 'Group:'], [`${C.GROUP_DIRECTORY}/${group.directory}/`, group.name], [null, `(${[ @@ -3373,7 +3693,7 @@ async function writeGroupPage(group) { `Gallery` ].join(', ') + (npGallery.length ? '; ' + npGallery : '')})`] ] - } + } : {simple: true}) }); } @@ -3381,10 +3701,9 @@ function getHrefOfAnythingMan(anythingMan) { return ( albumData.includes(anythingMan) ? C.ALBUM_DIRECTORY : trackData.includes(anythingMan) ? C.TRACK_DIRECTORY : - flashData.includes(anythingMan) ? C.FLASH_DIRECTORY : + flashData?.includes(anythingMan) ? C.FLASH_DIRECTORY : 'idk-bud' ) + '/' + ( - flashData.includes(anythingMan) ? getFlashDirectory(anythingMan) : anythingMan.directory ) + '/'; } @@ -3433,7 +3752,7 @@ function rebaseURLs(directory, html) { // no error: it's a full url } catch (error) { // caught an error: it's a component! - url = path.relative(directory, path.join(C.SITE_DIRECTORY, url)); + url = path.relative(directory, path.join(outputPath, url)); } return `${attr}="${url}"`; }); @@ -3446,6 +3765,75 @@ function classes(...args) { } async function main() { + const miscOptions = await parseOptions(process.argv.slice(2), { + 'data': { + type: 'value' + }, + + 'media': { + type: 'value' + }, + + 'out': { + type: 'value' + }, + + 'queue-size': { + type: 'value', + validate(size) { + if (parseInt(size) !== parseFloat(size)) return 'an integer'; + if (parseInt(size) < 0) return 'a counting number or zero'; + return true; + } + }, + queue: {alias: 'queue-size'}, + + [parseOptions.handleUnknown]: () => {} + }); + + dataPath = miscOptions.data || process.env.HSMUSIC_DATA; + mediaPath = miscOptions.media || process.env.HSMUSIC_MEDIA; + outputPath = miscOptions.out || process.env.HSMUSIC_OUT; + + { + let errored = false; + const error = (cond, msg) => { + if (cond) { + console.error(`\x1b[31;1m${msg}\x1b[0m`); + errored = true; + } + }; + error(!dataPath, `Expected --data option or HSMUSIC_DATA to be set`); + error(!mediaPath, `Expected --media option or HSMUSIC_MEDIA to be set`); + error(!outputPath, `Expected --out option or HSMUSIC_OUT to be set`); + if (errored) { + return; + } + } + + wikiInfo = await processWikiInfoFile(path.join(dataPath, WIKI_INFO_FILE)); + if (wikiInfo.error) { + console.log(`\x1b[31;1m${wikiInfo.error}\x1b[0m`); + return; + } + + homepageInfo = await processHomepageInfoFile(path.join(dataPath, HOMEPAGE_INFO_FILE)); + + if (homepageInfo.error) { + console.log(`\x1b[31;1m${homepageInfo.error}\x1b[0m`); + return; + } + + { + const errors = homepageInfo.rows.filter(obj => obj.error); + if (errors.length) { + for (const error of errors) { + console.log(`\x1b[31;1m${error.error}\x1b[0m`); + } + return; + } + } + // 8ut wait, you might say, how do we know which al8um these data files // correspond to???????? You wouldn't dare suggest we parse the actual // paths returned 8y this function, which ought to 8e of effectively @@ -3470,7 +3858,7 @@ async function main() { // avoiding that in our code 8ecause, again, we want to avoid assuming the // format of the returned paths here - they're only meant to 8e used for // reading as-is. - const albumDataFiles = await findAlbumDataFiles(); + const albumDataFiles = await findAlbumDataFiles(path.join(dataPath, C.DATA_ALBUM_DIRECTORY)); // Technically, we could do the data file reading and output writing at the // same time, 8ut that kinda makes the code messy, so I'm not 8othering @@ -3489,7 +3877,7 @@ async function main() { C.sortByDate(albumData); - artistData = await processArtistDataFile(path.join(C.DATA_DIRECTORY, ARTIST_DATA_FILE)); + artistData = await processArtistDataFile(path.join(dataPath, ARTIST_DATA_FILE)); if (artistData.error) { console.log(`\x1b[31;1m${artistData.error}\x1b[0m`); return; @@ -3507,18 +3895,20 @@ async function main() { trackData = C.getAllTracks(albumData); - flashData = await processFlashDataFile(path.join(C.DATA_DIRECTORY, FLASH_DATA_FILE)); - if (flashData.error) { - console.log(`\x1b[31;1m${flashData.error}\x1b[0m`); - return; - } + if (wikiInfo.features.flashesAndGames) { + flashData = await processFlashDataFile(path.join(dataPath, FLASH_DATA_FILE)); + if (flashData.error) { + console.log(`\x1b[31;1m${flashData.error}\x1b[0m`); + return; + } - const flashErrors = flashData.filter(obj => obj.error); - if (flashErrors.length) { - for (const error of flashErrors) { - console.log(`\x1b[31;1m${error.error}\x1b[0m`); + const errors = artistData.filter(obj => obj.error); + if (errors.length) { + for (const error of errors) { + console.log(`\x1b[31;1m${error.error}\x1b[0m`); + } + return; } - return; } artistNames = Array.from(new Set([ @@ -3533,13 +3923,13 @@ async function main() { ...track.contributors || [] ]) ]), - ...flashData.flatMap(flash => [ + ...(flashData?.flatMap(flash => [ ...flash.contributors || [] - ]) + ]) || []) ].map(contribution => contribution.who) ])); - tagData = await processTagDataFile(path.join(C.DATA_DIRECTORY, TAG_DATA_FILE)); + tagData = await processTagDataFile(path.join(dataPath, TAG_DATA_FILE)); if (tagData.error) { console.log(`\x1b[31;1m${tagData.error}\x1b[0m`); return; @@ -3555,7 +3945,7 @@ async function main() { } } - groupData = await processGroupDataFile(path.join(C.DATA_DIRECTORY, GROUP_DATA_FILE)); + groupData = await processGroupDataFile(path.join(dataPath, GROUP_DATA_FILE)); if (groupData.error) { console.log(`\x1b[31;1m${groupData.error}\x1b[0m`); return; @@ -3571,18 +3961,36 @@ async function main() { } } - newsData = await processNewsDataFile(path.join(C.DATA_DIRECTORY, NEWS_DATA_FILE)); - if (newsData.error) { - console.log(`\x1b[31;1m${newsData.error}\x1b[0m`); + staticPageData = await processStaticPageDataFile(path.join(dataPath, STATIC_PAGE_DATA_FILE)); + if (staticPageData.error) { + console.log(`\x1b[31;1m${staticPageData.error}\x1b[0m`); return; } - const newsErrors = newsData.filter(obj => obj.error); - if (newsErrors.length) { - for (const error of newsErrors) { - console.log(`\x1b[31;1m${error.error}\x1b[0m`); + { + const errors = staticPageData.filter(obj => obj.error); + if (errors.length) { + for (const error of errors) { + console.log(`\x1b[31;1m${error.error}\x1b[0m`); + } + return; + } + } + + if (wikiInfo.features.news) { + newsData = await processNewsDataFile(path.join(dataPath, NEWS_DATA_FILE)); + if (newsData.error) { + console.log(`\x1b[31;1m${newsData.error}\x1b[0m`); + return; + } + + const errors = newsData.filter(obj => obj.error); + if (errors.length) { + for (const error of errors) { + console.log(`\x1b[31;1m${error.error}\x1b[0m`); + } + return; } - return; } { @@ -3605,7 +4013,7 @@ async function main() { artistNames.sort((a, b) => a.toLowerCase() < b.toLowerCase() ? -1 : a.toLowerCase() > b.toLowerCase() ? 1 : 0); - justEverythingMan = C.sortByDate(albumData.concat(trackData, flashData.filter(flash => !flash.act8r8k))); + justEverythingMan = C.sortByDate(albumData.concat(trackData, flashData?.filter(flash => !flash.act8r8k) || [])); justEverythingSortedByArtDateMan = C.sortByArtDate(justEverythingMan.slice()); // console.log(JSON.stringify(justEverythingSortedByArtDateMan.map(getHrefOfAnythingMan), null, 2)); @@ -3719,7 +4127,7 @@ async function main() { contributionData = Array.from(new Set([ ...trackData.flatMap(track => [...track.artists || [], ...track.contributors || [], ...track.coverArtists || []]), ...albumData.flatMap(album => [...album.coverArtists || [], ...album.artists || []]), - ...flashData.flatMap(flash => [...flash.contributors || []]) + ...(flashData?.flatMap(flash => [...flash.contributors || []]) || []) ])); // Now that we have all the data, resolve references all 8efore actually @@ -3742,23 +4150,18 @@ async function main() { } }; - const actlessFlashData = flashData.filter(flash => !flash.act8r8k); - trackData.forEach(track => mapInPlace(track.references, getLinkedTrack)); trackData.forEach(track => track.aka = getLinkedTrack(track.aka)); trackData.forEach(track => mapInPlace(track.artTags, getLinkedTag)); albumData.forEach(album => mapInPlace(album.groups, getLinkedGroup)); albumData.forEach(album => mapInPlace(album.artTags, getLinkedTag)); artistData.forEach(artist => artist.alias = getLinkedArtist(artist.alias)); - actlessFlashData.forEach(flash => mapInPlace(flash.tracks, getLinkedTrack)); contributionData.forEach(contrib => contrib.who = getLinkedArtist(contrib.who)); filterNull(trackData, 'references'); filterNull(albumData, 'groups'); - filterNull(actlessFlashData, 'tracks'); trackData.forEach(track1 => track1.referencedBy = trackData.filter(track2 => track2.references.includes(track1))); - trackData.forEach(track => track.flashes = actlessFlashData.filter(flash => flash.tracks.includes(track))); groupData.forEach(group => group.albums = albumData.filter(album => album.groups.includes(group))); tagData.forEach(tag => tag.things = C.sortByArtDate([...albumData, ...trackData]).filter(thing => thing.artTags.includes(tag))); @@ -3767,10 +4170,22 @@ async function main() { ...trackData.filter(({ aka }) => aka === track) ].filter(Boolean)); + if (wikiInfo.features.flashesAndGames) { + const actlessFlashData = flashData.filter(flash => !flash.act8r8k); + + actlessFlashData.forEach(flash => mapInPlace(flash.tracks, getLinkedTrack)); + + filterNull(actlessFlashData, 'tracks'); + + trackData.forEach(track => track.flashes = actlessFlashData.filter(flash => flash.tracks.includes(track))); + } + artistData.forEach(artist => { const filterProp = (array, prop) => array.filter(thing => thing[prop]?.some(({ who }) => who === artist)); + const filterCommentary = array => array.filter(thing => thing.commentary && thing.commentary.replace(/<\/?b>/g, '').includes('' + artist.name + ':')); artist.tracks = { asArtist: filterProp(trackData, 'artists'), + asCommentator: filterCommentary(trackData), asContributor: filterProp(trackData, 'contributors'), asCoverArtist: filterProp(trackData, 'coverArtists'), asAny: trackData.filter(track => ( @@ -3779,11 +4194,14 @@ async function main() { }; artist.albums = { asArtist: filterProp(albumData, 'artists'), + asCommentator: filterCommentary(albumData), asCoverArtist: filterProp(albumData, 'coverArtists') }; - artist.flashes = { - asContributor: filterProp(flashData, 'contributors') - }; + if (wikiInfo.features.flashesAndGames) { + artist.flashes = { + asContributor: filterProp(flashData, 'contributors') + }; + } }); groupData.filter(x => x.isGroup).forEach(group => group.category = groupData.find(x => x.isCategory && x.name === group.category)); @@ -3792,20 +4210,6 @@ async function main() { officialAlbumData = albumData.filter(album => album.groups.some(group => group.directory === C.OFFICIAL_GROUP_DIRECTORY)); fandomAlbumData = albumData.filter(album => album.groups.every(group => group.directory !== C.OFFICIAL_GROUP_DIRECTORY)); - const miscOptions = await parseOptions(process.argv.slice(2), { - 'queue-size': { - type: 'value', - validate(size) { - if (parseInt(size) !== parseFloat(size)) return 'an integer'; - if (parseInt(size) < 0) return 'a counting number or zero'; - return true; - } - }, - queue: {alias: 'queue-size'}, - - [parseOptions.handleUnknown]: () => {} - }); - // Makes writing a little nicer on CPU theoretically, 8ut also costs in // performance right now 'cuz it'll w8 for file writes to 8e completed // 8efore moving on to more data processing. So, defaults to zero, which @@ -3826,6 +4230,7 @@ async function main() { group: {type: 'flag'}, list: {type: 'flag'}, misc: {type: 'flag'}, + static: {type: 'flag'}, tag: {type: 'flag'}, track: {type: 'flag'}, @@ -3836,13 +4241,14 @@ async function main() { await writeSymlinks(); if (buildAll || buildFlags.misc) await writeMiscellaneousPages(); + if (buildAll || buildFlags.static) await writeStaticPages(); if (buildAll || buildFlags.list) await writeListingPages(); if (buildAll || buildFlags.tag) await writeTagPages(); if (buildAll || buildFlags.group) await writeGroupPages(); if (buildAll || buildFlags.album) await writeAlbumPages(); if (buildAll || buildFlags.track) await writeTrackPages(); if (buildAll || buildFlags.artist) await writeArtistPages(); - if (buildAll || buildFlags.flash) await writeFlashPages(); + if (buildAll || buildFlags.flash) if (wikiInfo.features.flashesAndGames) await writeFlashPages(); decorateTime.displayTime(); -- cgit 1.3.0-6-gf8a5