From 234747721fec14e69fc75d6c0134ad4a5ae7736e Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Tue, 1 Jun 2021 15:32:03 -0300 Subject: basic module-ify album pages Other pages are commented out for now. Also, this doesn't include the source .txt processing functions yet, 8ut that'll pro8a8ly end up in the page/ files too. --- src/upd8.js | 576 ++++++++++-------------------------------------------------- 1 file changed, 90 insertions(+), 486 deletions(-) (limited to 'src/upd8.js') diff --git a/src/upd8.js b/src/upd8.js index 94fab3b..621cae5 100755 --- a/src/upd8.js +++ b/src/upd8.js @@ -109,8 +109,10 @@ import { unlink } from 'fs/promises'; -import find from './util/find.js'; import genThumbs from './gen-thumbs.js'; +import * as pageSpecs from './page/index.js'; + +import find from './util/find.js'; import * as html from './util/html.js'; import unbound_link from './util/link.js'; @@ -142,15 +144,29 @@ import { import { chunkByConditions, chunkByProperties, + getAlbumCover, + getAlbumListTag, getAllTracks, getArtistCommentary, getArtistNumContributions, + getFlashCover, getKebabCase, + getTotalDuration, + getTrackCover, sortByArtDate, sortByDate, sortByName } from './util/wiki-data.js'; +import { + serializeContribs, + serializeCover, + serializeGroupsForAlbum, + serializeGroupsForTrack, + serializeImagePaths, + serializeLink +} from './util/serialize.js'; + import { bindOpts, call, @@ -1488,10 +1504,6 @@ function getDurationInSeconds(string) { } } -function getTotalDuration(tracks) { - return tracks.reduce((duration, track) => duration + track.duration, 0); -} - const stringifyIndent = 0; const toRefs = (label, objectOrArray) => { @@ -1650,71 +1662,6 @@ function img({ } } -function serializeImagePaths(original) { - return { - original, - medium: thumb.medium(original), - small: thumb.small(original) - }; -} - -function serializeLink(thing) { - const ret = {}; - ret.name = thing.name; - ret.directory = thing.directory; - if (thing.color) ret.color = thing.color; - return ret; -} - -function serializeContribs(contribs) { - return contribs.map(({ who, what }) => { - const ret = {}; - ret.artist = serializeLink(who); - if (what) ret.contribution = what; - return ret; - }); -} - -function serializeCover(thing, pathFunction) { - const coverPath = pathFunction(thing, { - to: urls.from('media.root').to - }); - - const { artTags } = thing; - - const cwTags = artTags.filter(tag => tag.isCW); - const linkTags = artTags.filter(tag => !tag.isCW); - - return { - paths: serializeImagePaths(coverPath), - tags: linkTags.map(serializeLink), - warnings: cwTags.map(tag => tag.name) - }; -} - -function serializeGroupsForAlbum(album) { - return album.groups.map(group => { - const index = group.albums.indexOf(album); - const next = group.albums[index + 1] || null; - const previous = group.albums[index - 1] || null; - return {group, index, next, previous}; - }).map(({group, index, next, previous}) => ({ - link: serializeLink(group), - descriptionShort: group.descriptionShort, - albumIndex: index, - nextAlbum: next && serializeLink(next), - previousAlbum: previous && serializeLink(previous), - urls: group.urls - })); -} - -function serializeGroupsForTrack(track) { - return track.album.groups.map(group => ({ - link: serializeLink(group), - urls: group.urls, - })); -} - function validateWritePath(path, urlGroup) { if (!Array.isArray(path)) { return {error: `Expected array, got ${path}`}; @@ -2686,218 +2633,6 @@ function writeIndexAndTrackPagesForAlbum(album) { } */ -function writeAlbumPages({wikiData}) { - return wikiData.albumData.map(album => writeAlbumPage(album, {wikiData})); -} - -function writeAlbumPage(album, {wikiData}) { - const { wikiInfo } = wikiData; - - const trackToListItem = (track, {getArtistString, link, strings}) => { - const itemOpts = { - duration: strings.count.duration(track.duration), - track: link.track(track) - }; - return `
  • ${ - (track.artists === album.artists - ? strings('trackList.item.withDuration', itemOpts) - : strings('trackList.item.withDuration.withArtists', { - ...itemOpts, - by: `${ - strings('trackList.item.withArtists.by', { - artists: getArtistString(track.artists) - }) - }` - })) - }
  • `; - }; - - const commentaryEntries = [album, ...album.tracks].filter(x => x.commentary).length; - const albumDuration = getTotalDuration(album.tracks); - - const listTag = getAlbumListTag(album); - - const data = { - type: 'data', - path: ['album', album.directory], - data: () => ({ - name: album.name, - directory: album.directory, - dates: { - released: album.date, - trackArtAdded: album.trackArtDate, - coverArtAdded: album.coverArtDate, - addedToWiki: album.dateAdded - }, - duration: albumDuration, - color: album.color, - cover: serializeCover(album, getAlbumCover), - artists: serializeContribs(album.artists || []), - coverArtists: serializeContribs(album.coverArtists || []), - wallpaperArtists: serializeContribs(album.wallpaperArtists || []), - bannerArtists: serializeContribs(album.bannerArtists || []), - groups: serializeGroupsForAlbum(album), - trackGroups: album.trackGroups?.map(trackGroup => ({ - name: trackGroup.name, - color: trackGroup.color, - tracks: trackGroup.tracks.map(track => track.directory) - })), - tracks: album.tracks.map(track => ({ - link: serializeLink(track), - duration: track.duration - })) - }) - }; - - const page = { - type: 'page', - path: ['album', album.directory], - page: ({ - generateCoverLink, - getAlbumStylesheet, - getArtistString, - link, - strings, - transformMultiline - }) => ({ - title: strings('albumPage.title', {album: album.name}), - stylesheet: getAlbumStylesheet(album), - theme: getThemeString(album.color, [ - `--album-directory: ${album.directory}` - ]), - - banner: album.bannerArtists && { - dimensions: album.bannerDimensions, - path: ['media.albumBanner', album.directory], - alt: strings('misc.alt.albumBanner'), - position: 'top' - }, - - main: { - content: fixWS` - ${generateCoverLink({ - path: ['media.albumCover', album.directory], - alt: strings('misc.alt.albumCover'), - tags: album.artTags - })} -

    ${strings('albumPage.title', {album: album.name})}

    -

    - ${[ - album.artists && strings('releaseInfo.by', { - artists: getArtistString(album.artists, { - showContrib: true, - showIcons: true - }) - }), - album.coverArtists && strings('releaseInfo.coverArtBy', { - artists: getArtistString(album.coverArtists, { - showContrib: true, - showIcons: true - }) - }), - album.wallpaperArtists && strings('releaseInfo.wallpaperArtBy', { - artists: getArtistString(album.wallpaperArtists, { - showContrib: true, - showIcons: true - }) - }), - album.bannerArtists && strings('releaseInfo.bannerArtBy', { - artists: getArtistString(album.bannerArtists, { - showContrib: true, - showIcons: true - }) - }), - strings('releaseInfo.released', { - date: strings.count.date(album.date) - }), - +album.coverArtDate !== +album.date && strings('releaseInfo.artReleased', { - date: strings.count.date(album.coverArtDate) - }), - strings('releaseInfo.duration', { - duration: strings.count.duration(albumDuration, {approximate: album.tracks.length > 1}) - }) - ].filter(Boolean).join('
    \n')} -

    - ${commentaryEntries && `

    ${ - strings('releaseInfo.viewCommentary', { - link: link.albumCommentary(album, { - text: strings('releaseInfo.viewCommentary.link') - }) - }) - }

    `} - ${album.urls.length && `

    ${ - strings('releaseInfo.listenOn', { - links: strings.list.or(album.urls.map(url => fancifyURL(url, {album: true, strings}))) - }) - }

    `} - ${album.trackGroups ? fixWS` -
    - ${album.trackGroups.map(({ name, color, startIndex, tracks }) => fixWS` -
    ${ - strings('trackList.group', { - duration: strings.count.duration(getTotalDuration(tracks), {approximate: tracks.length > 1}), - group: name - }) - }
    -
    <${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}> - ${tracks.map(t => trackToListItem(t, {getArtistString, link, strings})).join('\n')} -
    - `).join('\n')} -
    - ` : fixWS` - <${listTag}> - ${album.tracks.map(t => trackToListItem(t, {getArtistString, link, strings})).join('\n')} - - `} -

    - ${[ - strings('releaseInfo.addedToWiki', { - date: strings.count.date(album.dateAdded) - }) - ].filter(Boolean).join('
    \n')} -

    - ${album.commentary && fixWS` -

    ${strings('releaseInfo.artistCommentary')}

    -
    - ${transformMultiline(album.commentary)} -
    - `} - ` - }, - - sidebarLeft: generateSidebarForAlbum(album, { - link, - strings, - transformMultiline, - wikiData - }), - - nav: { - links: [ - {toHome: true}, - { - html: strings('albumPage.nav.album', { - album: link.album(album, {class: 'current'}) - }) - }, - album.tracks.length > 1 && - { - divider: false, - html: generateAlbumNavLinks(album, null, {link, strings}) - } - ], - content: fixWS` -
    - ${generateAlbumChronologyLinks(album, null, {link, strings})} -
    - ` - } - }) - }; - - return [page, data]; -} - function getAlbumStylesheet(album, {to}) { return [ album.wallpaperArtists && fixWS` @@ -5068,14 +4803,6 @@ function getTagDirectory({name}) { return getKebabCase(name); } -function getAlbumListTag(album) { - if (album.directory === UNRELEASED_TRACKS_DIRECTORY) { - return 'ul'; - } else { - return 'ol'; - } -} - function fancifyURL(url, {strings, album = false} = {}) { const domain = new URL(url).hostname; return fixWS`${ @@ -5196,156 +4923,6 @@ function chronologyLinks(currentThing, { }).filter(Boolean).join('\n'); } -function generateAlbumNavLinks(album, currentTrack, {link, strings}) { - if (album.tracks.length <= 1) { - return ''; - } - - const previousNextLinks = currentTrack && generatePreviousNextLinks(currentTrack, { - link, strings, - data: album.tracks, - linkKey: 'track' - }); - const randomLink = `${ - (currentTrack - ? strings('trackPage.nav.random') - : strings('albumPage.nav.randomTrack')) - }`; - - return (previousNextLinks - ? `(${previousNextLinks}, ${randomLink})` - : `(${randomLink})`); -} - -function generateAlbumChronologyLinks(album, currentTrack, {link, strings}) { - return [ - currentTrack && chronologyLinks(currentTrack, { - contribKey: 'artists', - getThings: artist => [...artist.tracks.asArtist, ...artist.tracks.asContributor], - headingString: 'misc.chronology.heading.track', - strings, - link, - wikiData - }), - chronologyLinks(currentTrack || album, { - contribKey: 'coverArtists', - getThings: artist => [...artist.albums.asCoverArtist, ...artist.tracks.asCoverArtist], - headingString: 'misc.chronology.heading.coverArt', - link, - strings, - wikiData - }) - ].filter(Boolean).join('\n'); -} - -function generateSidebarForAlbum(album, { - currentTrack = null, - link, - strings, - transformMultiline, - wikiData -}) { - const listTag = getAlbumListTag(album); - - const trackGroups = album.trackGroups || [{ - name: strings('albumSidebar.trackList.fallbackGroupName'), - color: album.color, - startIndex: 0, - tracks: album.tracks - }]; - - const trackToListItem = track => `
  • ${ - strings('albumSidebar.trackList.item', { - track: link.track(track) - }) - }
  • `; - - const trackListPart = fixWS` -

    ${link.album(album)}

    - ${trackGroups.map(({ name, color, startIndex, tracks }) => - html.tag('details', { - // Leave side8ar track groups collapsed on al8um homepage, - // since there's already a view of all the groups expanded - // in the main content area. - open: currentTrack && tracks.includes(currentTrack), - class: tracks.includes(currentTrack) && 'current' - }, [ - html.tag('summary', - {style: getLinkThemeString(color)}, - (listTag === 'ol' - ? strings('albumSidebar.trackList.group.withRange', { - group: `${name}`, - range: `${startIndex + 1}–${startIndex + tracks.length}` - }) - : strings('albumSidebar.trackList.group', { - group: `${name}` - })) - ), - fixWS` - <${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}> - ${tracks.map(trackToListItem).join('\n')} - - ` - ])).join('\n')} - `; - - const { groups } = album; - - const groupParts = groups.map(group => { - const index = group.albums.indexOf(album); - const next = group.albums[index + 1]; - const previous = group.albums[index - 1]; - return {group, next, previous}; - }).map(({group, next, previous}) => fixWS` -

    ${ - strings('albumSidebar.groupBox.title', { - group: link.groupInfo(group) - }) - }

    - ${!currentTrack && transformMultiline(group.descriptionShort)} - ${group.urls.length && `

    ${ - strings('releaseInfo.visitOn', { - links: strings.list.or(group.urls.map(url => fancifyURL(url, {strings}))) - }) - }

    `} - ${!currentTrack && fixWS` - ${next && ``} - ${previous && ``} - `} - `); - - if (groupParts.length) { - if (currentTrack) { - const combinedGroupPart = groupParts.join('\n
    \n'); - return { - multiple: [ - trackListPart, - combinedGroupPart - ] - }; - } else { - return { - multiple: [ - ...groupParts, - trackListPart - ] - }; - } - } else { - return { - content: trackListPart - }; - } -} - function generateSidebarForGroup(currentGroup, isGallery, {link, strings, wikiData}) { const { groupCategoryData, wikiInfo } = wikiData; @@ -5606,28 +5183,6 @@ function linkAnythingMan(anythingMan, {link, wikiData, ...opts}) { ) } -function getAlbumCover(album, {to}) { - return to('media.albumCover', album.directory); -} - -function getTrackCover(track, {to}) { - // Some al8ums don't have any track art at all, and in those, every track - // just inherits the al8um's own cover art. - if (track.coverArtists === null) { - return getAlbumCover(track.album, {to}); - } else { - return to('media.trackCover', track.album.directory, track.directory); - } -} - -function getFlashCover(flash, {to}) { - return to('media.flashArt', flash.directory); -} - -function getFlashLink(flash) { - return `https://homestuck.com/story/${flash.page}`; -} - function classes(...args) { const values = args.filter(Boolean); return `class="${values.join(' ')}"`; @@ -6316,6 +5871,7 @@ async function main() { await writeSymlinks(); await writeSharedFilesAndPages({strings: defaultStrings, wikiData}); + /* const buildDictionary = { misc: writeMiscellaneousPages, news: writeNewsPages, @@ -6329,12 +5885,14 @@ async function main() { artist: writeArtistPages, flash: writeFlashPages }; + */ + + const buildDictionary = pageSpecs; const buildSteps = (writeAll ? Object.values(buildDictionary) : (Object.entries(buildDictionary) - .filter(([ flag ]) => writeFlags[flag]) - .map(([ flag, fn ]) => fn))); + .filter(([ flag ]) => writeFlags[flag]))); // *NB: While what's 8elow is 8asically still true in principle, the // format is QUITE DIFFERENT than what's descri8ed here! There @@ -6351,18 +5909,27 @@ async function main() { { let error = false; - writes = buildSteps.flatMap(fn => { - const fns = fn({wikiData}) || []; + const targets = buildSteps.flatMap(([ flag, pageSpec ]) => { + const targets = pageSpec.targets({wikiData}); + return targets.map(target => ({flag, pageSpec, target})); + }); + + const writeArrays = await progressPromiseAll(`Processing build data to be shared across langauges.`, queue( + targets.map(({ flag, pageSpec, target }) => () => { + const writes = pageSpec.write(target, {wikiData}) || []; + + // Do a quick valid8tion! If one of the writeThingPages functions go + // wrong, this will stall out early and tell us which did. + + if (!Array.isArray(writes)) { + logError`${flag + '.write'} didn't return an array!`; + error = true; + return []; + } - // Do a quick valid8tion! If one of the writeThingPages functions go - // wrong, this will stall out early and tell us which did. - if (!Array.isArray(fns)) { - logError`${fn.name} didn't return an array!`; - error = true; - } else if (fns.every(entry => Array.isArray(entry))) { if (!( - fns.every(entry => entry.every(obj => typeof obj === 'object')) && - fns.every(entry => entry.every(obj => { + writes.every(obj => typeof obj === 'object') && + writes.every(obj => { const result = validateWriteObject(obj); if (result.error) { logError`Validating write object failed: ${result.error}`; @@ -6370,24 +5937,23 @@ async function main() { } else { return true; } - })) + }) )) { - logError`${fn.name} uses updated format, but entries are invalid!`; + logError`${flag + '.write'} uses updated format, but entries are invalid!`; error = true; + return []; } - return fns.flatMap(writes => writes); - } else if (fns.some(fn => typeof fn !== 'function')) { - logError`${fn.name} didn't return all functions or all arrays!`; - error = true; - } - - return fns; - }); + return writes; + }), + queueSize + )); if (error) { return; } + + writes = writeArrays.flatMap(writes => writes); } const pageWrites = writes.filter(({ type }) => type === 'page'); @@ -6395,8 +5961,36 @@ async function main() { const redirectWrites = writes.filter(({ type }) => type === 'redirect'); await progressPromiseAll(`Writing data files shared across languages.`, queue( - // TODO: This only supports one <>-style argument. - dataWrites.map(({path, data}) => () => writeData(path[0], path[1], data())), + dataWrites.map(({path, data}) => () => { + const bound = {}; + + bound.serializeLink = bindOpts(serializeLink, {}); + + bound.serializeContribs = bindOpts(serializeContribs, {}); + + bound.serializeImagePaths = bindOpts(serializeImagePaths, { + thumb + }); + + bound.serializeCover = bindOpts(serializeCover, { + [bindOpts.bindIndex]: 2, + serializeImagePaths: bound.serializeImagePaths, + urls + }); + + bound.serializeGroupsForAlbum = bindOpts(serializeGroupsForAlbum, { + serializeLink + }); + + bound.serializeGroupsForTrack = bindOpts(serializeGroupsForTrack, { + serializeLink + }); + + // TODO: This only supports one <>-style argument. + return writeData(path[0], path[1], data({ + ...bound + })); + }), queueSize )); @@ -6453,6 +6047,10 @@ async function main() { to }); + bound.fancifyURL = bindOpts(fancifyURL, { + strings + }); + bound.getArtistString = bindOpts(getArtistString, { iconifyURL: bound.iconifyURL, link: bound.link, @@ -6471,6 +6069,12 @@ async function main() { to }); + bound.chronologyLinks = bindOpts(chronologyLinks, { + link: bound.link, + strings, + wikiData + }); + bound.generateCoverLink = bindOpts(generateCoverLink, { [bindOpts.bindIndex]: 0, link: bound.link, -- cgit 1.3.0-6-gf8a5