From dc873feb1cf1c1a442e17e15766276d9ae1e7443 Mon Sep 17 00:00:00 2001 From: Florrie Date: Fri, 24 Jul 2020 16:13:50 -0300 Subject: recompose, refine --- upd8.js | 339 +++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 271 insertions(+), 68 deletions(-) (limited to 'upd8.js') diff --git a/upd8.js b/upd8.js index 7c0345a6..bffd50d5 100644 --- a/upd8.js +++ b/upd8.js @@ -295,27 +295,51 @@ function getMultilineField(lines, name) { return listLines.map(line => line.slice(4)).join('\n'); }; -function transformMultiline(text) { +function transformMultiline(text, treatAsDocument=false) { // Heck yes, HTML magics. - text = text.replace(/\[\[(.+?)\]\]/g, (match, ref) => { - const track = getLinkedTrack(ref); - if (track) { - let name = ref.match(/(.*):/); - if (name) { - name = name[1]; + text = text.replace(/\[\[(album:|flash:)?(.+?)\]\]/g, (match, category, ref) => { + if (category === 'album:') { + const album = getLinkedAlbum(ref); + if (album) { + return fixWS` + ${album.name} + `; } else { - name = track.name; + console.warn(`\x1b[33mThe linked album ${match} does not exist!\x1b[0m`); + return ref; + } + } else if (category === 'flash:') { + const flash = getLinkedFlash(ref); + if (flash) { + return getFlashLinkHTML(flash); + } else { + console.warn(`\x1b[33mThe linked flash ${match} does not exist!\x1b[0m`); + return ref; } - return fixWS` - ${name} - `; } else { - console.warn(`\x1b[33mThe linked track ${match} does not exist!\x1b[0m`); - return ref; + const track = getLinkedTrack(ref); + if (track) { + let name = ref.match(/(.*):/); + if (name) { + name = name[1]; + } else { + name = track.name; + } + return fixWS` + ${name} + `; + } else { + console.warn(`\x1b[33mThe linked track ${match} does not exist!\x1b[0m`); + return ref; + } } }); + if (treatAsDocument) { + return text; + } + const outLines = []; let inList = false; @@ -422,7 +446,12 @@ async function processAlbumDataFile(file) { // future or whatever. const albumColorFG = getBasicField(albumSection, 'FG') || '#0088ff'; const albumColorBG = getBasicField(albumSection, 'BG') || '#222222'; - const albumTheme = getBasicField(albumSection, 'Theme') || 0; + const albumThemeBluhBluh = getBasicField(albumSection, 'Theme') || 0; + const albumTheme = { + fg: albumColorFG, + bg: albumColorBG, + theme: albumThemeBluhBluh + }; if (!albumName) { return {error: 'Expected "Album" (name) field!'}; @@ -462,14 +491,14 @@ async function processAlbumDataFile(file) { isBeyond, isOfficial, isFanon, - theme: { - fg: albumColorFG, - bg: albumColorBG, - theme: albumTheme - }, - tracks + theme: albumTheme, + tracks, + usesGroups: false }; + let group = ''; + let groupTheme = albumTheme; + for (const section of sections.slice(1)) { // Just skip empty sections. Sometimes I paste a 8unch of dividers, // and this lets the empty sections doing that creates (temporarily) @@ -478,6 +507,23 @@ async function processAlbumDataFile(file) { continue; } + const groupName = getBasicField(section, 'Group'); + if (groupName) { + group = groupName; + albumData.usesGroups = true; + + const groupColorFG = getBasicField(section, 'FG'); + const groupColorBG = getBasicField(section, 'BG'); + const iDontRememberWhatThisVariableDoesTheme = getBasicField(section, 'Theme'); + groupTheme = Object.assign({}, albumTheme, Object.fromEntries([ + ['fg', groupColorFG], + ['bg', groupColorBG], + ['theme', iDontRememberWhatThisVariableDoesTheme] + ].filter(([k, v]) => v))); + + continue; + } + const trackName = getBasicField(section, 'Track'); const trackCommentary = getCommentaryField(section); const trackLyrics = getMultilineField(section, 'Lyrics'); @@ -489,6 +535,19 @@ async function processAlbumDataFile(file) { let trackContributors = getContributionField(section, 'Contributors') || []; let trackDirectory = getBasicField(section, 'Directory'); + if (!trackName) { + return {error: 'A track section is missing the "Track" (name) field.'}; + } + + let trackDuration = getBasicField(section, 'Duration'); + + if (!trackDuration) { + // return {error: `The track "${trackName}" is missing the "Duration" field.`}; + trackDuration = '0:00'; + } + + trackDuration = getDurationInSeconds(trackDuration); + if (trackContributors.error) { return {error: `${trackContributors.error} (in ${trackName}, ${albumName})`}; } @@ -497,10 +556,6 @@ async function processAlbumDataFile(file) { return {error: `${trackCommentary.error} (in ${trackName}, ${albumName})`}; } - if (!trackName) { - return {error: 'A track section is missing the "Track" (name) field.'}; - } - if (!trackArtists) { // If an al8um has an artist specified (usually 8ecause it's a solo // al8um), let tracks inherit that artist. We won't display the @@ -556,6 +611,7 @@ async function processAlbumDataFile(file) { artists: trackArtists, coverArtists: trackCoverArtists, contributors: trackContributors, + duration: trackDuration, commentary: trackCommentary, lyrics: trackLyrics, references, @@ -567,6 +623,8 @@ async function processAlbumDataFile(file) { isBeyond, isOfficial, isFanon, + group, + theme: group ? groupTheme : albumTheme, // 8ack-reference the al8um o8ject! This is very useful for when // we're outputting the track pages. album: albumData @@ -661,8 +719,48 @@ async function processFlashDataFile(file) { } function getDateString({ date }) { + /* const pad = val => val.toString().padStart(2, '0'); return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`; + */ + const months = [ + 'January', 'February', 'March', 'April', 'May', 'June', + 'July', 'August', 'September', 'October', 'November', 'December' + ] + return `${date.getDate()} ${months[date.getMonth()]} ${date.getFullYear()}` +} + +function getDurationString(secTotal) { + if (secTotal === 0) { + return '_:__' + } + + let hour = Math.floor(secTotal / 3600) + let min = Math.floor((secTotal - hour * 3600) / 60) + let sec = Math.floor(secTotal - hour * 3600 - min * 60) + + const pad = val => val.toString().padStart(2, '0') + + if (hour > 0) { + return `${hour}:${pad(min)}:${pad(sec)}` + } else { + return `${min}:${pad(sec)}` + } +} + +function getDurationInSeconds(string) { + const parts = string.split(':').map(n => parseInt(n)) + if (parts.length === 3) { + return parts[0] * 3600 + parts[1] * 60 + parts[2] + } else if (parts.length === 2) { + return parts[0] * 60 + parts[1] + } else { + return 0 + } +} + +function getTotalDuration(tracks) { + return tracks.reduce((duration, track) => duration + track.duration, 0); } function stringifyAlbumData() { @@ -765,7 +863,7 @@ function writeMiscellaneousPages() { ${album.name} `).join('\n')} - ...and more to be added soon + ...and more to be added at your request

Official

The original discography: a replica of the Homestuck Bandcamp prior to the enmergening.
Albums organized by What Pumpkin. 2009–2019.

@@ -828,7 +926,7 @@ function writeMiscellaneousPages() {

Changelog

(Home)

- ${SITE_CHANGELOG} + ${transformMultiline(SITE_CHANGELOG, true)}
@@ -871,6 +969,15 @@ function writeIndexAndTrackPagesForAlbum(album) { } async function writeAlbumPage(album) { + const trackToListItem = track => fixWS` +
  • + (${getDurationString(track.duration)}) + ${track.name} + ${track.artists !== album.artists && fixWS` + by ${getArtistString(track.artists)} + ` || ``} +
  • + `; const listTag = getAlbumListTag(album); await writePage([C.ALBUM_DIRECTORY, album.directory], album.name, fixWS` @@ -891,18 +998,27 @@ async function writeAlbumPage(album) { `))}.
    ` || ``} Released ${getDateString(album)}. ${+album.artDate !== +album.date && `
    Art released ${getDateString({date: album.artDate})}.` || ``} +
    Duration: ~${getDurationString(getTotalDuration(album.tracks))}.

    ${album.urls.length && `

    Listen on ${joinNoOxford(album.urls.map(url => fancifyURL(url, {album: true})), 'or')}.

    ` || ``} - <${listTag}> - ${album.tracks.map(track => fixWS` -
  • - ${track.name} - ${track.artists !== album.artists && fixWS` - by ${getArtistString(track.artists)} - ` || ``} -
  • - `).join('\n')} - + ${album.usesGroups ? fixWS` +

    This album listing is divided into groups:

    +
    + ${album.tracks.flatMap((track, i, arr) => [ + (i > 0 && track.group !== arr[i - 1].group) && ``, + (i === 0 || track.group !== arr[i - 1].group) && fixWS` +
    ${track.group}:
    +
    <${listTag}> + `, + trackToListItem(track), + i === arr.length && `
    ` + ].filter(Boolean)).join('\n')} +
    + ` : fixWS` + <${listTag}> + ${album.tracks.map(trackToListItem).join('\n')} + + `} ${album.commentary && fixWS`

    Artist commentary:

    @@ -922,7 +1038,7 @@ async function writeTrackPage(track) { const tracksReferenced = getTracksReferencedBy(track); const flashesThatFeature = getFlashesThatFeature(track); await writePage([C.TRACK_DIRECTORY, track.directory], track.name, fixWS` - + @@ -940,6 +1056,7 @@ async function writeTrackPage(track) { `))}.` || ``} ${track.album.directory !== C.UNRELEASED_TRACKS_DIRECTORY && `
    Released ${getDateString(track)}.` || ``} ${+track.artDate !== +track.date && `
    Art released ${getDateString({date: track.artDate})}.` || ``} + ${track.duration && `
    Duration: ${getDurationString(track.duration)}.` || ``}

    ${track.urls.length ? fixWS`

    Listen on ${joinNoOxford(track.urls.map(fancifyURL), 'or')}.

    @@ -965,7 +1082,7 @@ async function writeTrackPage(track) {