diff options
Diffstat (limited to 'src/page')
-rw-r--r-- | src/page/album-commentary.js | 261 | ||||
-rw-r--r-- | src/page/album.js | 960 | ||||
-rw-r--r-- | src/page/artist-alias.js | 25 | ||||
-rw-r--r-- | src/page/artist.js | 1142 | ||||
-rw-r--r-- | src/page/flash.js | 474 | ||||
-rw-r--r-- | src/page/group.js | 488 | ||||
-rw-r--r-- | src/page/homepage.js | 269 | ||||
-rw-r--r-- | src/page/index.js | 24 | ||||
-rw-r--r-- | src/page/listing.js | 341 | ||||
-rw-r--r-- | src/page/news.js | 203 | ||||
-rw-r--r-- | src/page/static.js | 41 | ||||
-rw-r--r-- | src/page/tag.js | 157 | ||||
-rw-r--r-- | src/page/track.js | 674 |
13 files changed, 2924 insertions, 2135 deletions
diff --git a/src/page/album-commentary.js b/src/page/album-commentary.js index 57135a4a..3c197239 100644 --- a/src/page/album-commentary.js +++ b/src/page/album-commentary.js @@ -2,143 +2,182 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; -import { - filterAlbumsByCommentary -} from '../util/wiki-data.js'; +import { filterAlbumsByCommentary } from "../util/wiki-data.js"; // Page exports -export function condition({wikiData}) { - return filterAlbumsByCommentary(wikiData.albumData).length; +export function condition({ wikiData }) { + return filterAlbumsByCommentary(wikiData.albumData).length; } -export function targets({wikiData}) { - return filterAlbumsByCommentary(wikiData.albumData); +export function targets({ wikiData }) { + return filterAlbumsByCommentary(wikiData.albumData); } -export function write(album, {wikiData}) { - const { wikiInfo } = wikiData; - - const entries = [album, ...album.tracks].filter(x => x.commentary).map(x => x.commentary); - const words = entries.join(' ').split(' ').length; - - const page = { - type: 'page', - path: ['albumCommentary', album.directory], - page: ({ - getAlbumStylesheet, - getLinkThemeString, - getThemeString, - link, - language, - to, - transformMultiline - }) => ({ - title: language.$('albumCommentaryPage.title', {album: album.name}), - stylesheet: getAlbumStylesheet(album), - theme: getThemeString(album.color), - - main: { - content: fixWS` +export function write(album, { wikiData }) { + const { wikiInfo } = wikiData; + + const entries = [album, ...album.tracks] + .filter((x) => x.commentary) + .map((x) => x.commentary); + const words = entries.join(" ").split(" ").length; + + const page = { + type: "page", + path: ["albumCommentary", album.directory], + page: ({ + getAlbumStylesheet, + getLinkThemeString, + getThemeString, + link, + language, + to, + transformMultiline, + }) => ({ + title: language.$("albumCommentaryPage.title", { album: album.name }), + stylesheet: getAlbumStylesheet(album), + theme: getThemeString(album.color), + + main: { + content: fixWS` <div class="long-content"> - <h1>${language.$('albumCommentaryPage.title', { - album: link.album(album) + <h1>${language.$("albumCommentaryPage.title", { + album: link.album(album), })}</h1> - <p>${language.$('albumCommentaryPage.infoLine', { - words: `<b>${language.formatWordCount(words, {unit: true})}</b>`, - entries: `<b>${language.countCommentaryEntries(entries.length, {unit: true})}</b>` + <p>${language.$("albumCommentaryPage.infoLine", { + words: `<b>${language.formatWordCount(words, { + unit: true, + })}</b>`, + entries: `<b>${language.countCommentaryEntries( + entries.length, + { unit: true } + )}</b>`, })}</p> - ${album.commentary && fixWS` - <h3>${language.$('albumCommentaryPage.entry.title.albumCommentary')}</h3> + ${ + album.commentary && + fixWS` + <h3>${language.$( + "albumCommentaryPage.entry.title.albumCommentary" + )}</h3> <blockquote> ${transformMultiline(album.commentary)} </blockquote> - `} - ${album.tracks.filter(t => t.commentary).map(track => fixWS` - <h3 id="${track.directory}">${language.$('albumCommentaryPage.entry.title.trackCommentary', { - track: link.track(track) - })}</h3> - <blockquote style="${getLinkThemeString(track.color)}"> + ` + } + ${album.tracks + .filter((t) => t.commentary) + .map( + (track) => fixWS` + <h3 id="${track.directory}">${language.$( + "albumCommentaryPage.entry.title.trackCommentary", + { + track: link.track(track), + } + )}</h3> + <blockquote style="${getLinkThemeString( + track.color + )}"> ${transformMultiline(track.commentary)} </blockquote> - `).join('\n')} + ` + ) + .join("\n")} </div> - ` - }, - - nav: { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - { - path: ['localized.commentaryIndex'], - title: language.$('commentaryIndex.title') - }, - { - html: language.$('albumCommentaryPage.nav.album', { - album: link.albumCommentary(album, {class: 'current'}) - }) - } - ] - } - }) - }; - - return [page]; + `, + }, + + nav: { + linkContainerClasses: ["nav-links-hierarchy"], + links: [ + { toHome: true }, + { + path: ["localized.commentaryIndex"], + title: language.$("commentaryIndex.title"), + }, + { + html: language.$("albumCommentaryPage.nav.album", { + album: link.albumCommentary(album, { class: "current" }), + }), + }, + ], + }, + }), + }; + + return [page]; } -export function writeTargetless({wikiData}) { - const data = filterAlbumsByCommentary(wikiData.albumData) - .map(album => ({ - album, - entries: [album, ...album.tracks].filter(x => x.commentary).map(x => x.commentary) - })) - .map(({ album, entries }) => ({ - album, entries, - words: entries.join(' ').split(' ').length - })); - - const totalEntries = data.reduce((acc, {entries}) => acc + entries.length, 0); - const totalWords = data.reduce((acc, {words}) => acc + words, 0); - - const page = { - type: 'page', - path: ['commentaryIndex'], - page: ({ - link, - language - }) => ({ - title: language.$('commentaryIndex.title'), - - main: { - content: fixWS` +export function writeTargetless({ wikiData }) { + const data = filterAlbumsByCommentary(wikiData.albumData) + .map((album) => ({ + album, + entries: [album, ...album.tracks] + .filter((x) => x.commentary) + .map((x) => x.commentary), + })) + .map(({ album, entries }) => ({ + album, + entries, + words: entries.join(" ").split(" ").length, + })); + + const totalEntries = data.reduce( + (acc, { entries }) => acc + entries.length, + 0 + ); + const totalWords = data.reduce((acc, { words }) => acc + words, 0); + + const page = { + type: "page", + path: ["commentaryIndex"], + page: ({ link, language }) => ({ + title: language.$("commentaryIndex.title"), + + main: { + content: fixWS` <div class="long-content"> - <h1>${language.$('commentaryIndex.title')}</h1> - <p>${language.$('commentaryIndex.infoLine', { - words: `<b>${language.formatWordCount(totalWords, {unit: true})}</b>`, - entries: `<b>${language.countCommentaryEntries(totalEntries, {unit: true})}</b>` + <h1>${language.$("commentaryIndex.title")}</h1> + <p>${language.$("commentaryIndex.infoLine", { + words: `<b>${language.formatWordCount(totalWords, { + unit: true, + })}</b>`, + entries: `<b>${language.countCommentaryEntries( + totalEntries, + { unit: true } + )}</b>`, })}</p> - <p>${language.$('commentaryIndex.albumList.title')}</p> + <p>${language.$("commentaryIndex.albumList.title")}</p> <ul> ${data - .map(({ album, entries, words }) => fixWS` - <li>${language.$('commentaryIndex.albumList.item', { + .map( + ({ album, entries, words }) => fixWS` + <li>${language.$( + "commentaryIndex.albumList.item", + { album: link.albumCommentary(album), - words: language.formatWordCount(words, {unit: true}), - entries: language.countCommentaryEntries(entries.length, {unit: true}) - })}</li> - `) - .join('\n')} + words: language.formatWordCount(words, { + unit: true, + }), + entries: + language.countCommentaryEntries( + entries.length, + { unit: true } + ), + } + )}</li> + ` + ) + .join("\n")} </ul> </div> - ` - }, + `, + }, - nav: {simple: true} - }) - }; + nav: { simple: true }, + }), + }; - return [page]; + return [page]; } diff --git a/src/page/album.js b/src/page/album.js index c265fdc6..48747d7f 100644 --- a/src/page/album.js +++ b/src/page/album.js @@ -2,297 +2,394 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; -import * as html from '../util/html.js'; +import * as html from "../util/html.js"; -import { - bindOpts, - compareArrays, -} from '../util/sugar.js'; +import { bindOpts, compareArrays } from "../util/sugar.js"; import { - getAlbumCover, - getAlbumListTag, - getTotalDuration, -} from '../util/wiki-data.js'; + getAlbumCover, + getAlbumListTag, + getTotalDuration, +} from "../util/wiki-data.js"; // Page exports -export function targets({wikiData}) { - return wikiData.albumData; +export function targets({ wikiData }) { + return wikiData.albumData; } -export function write(album, {wikiData}) { - const { wikiInfo } = wikiData; +export function write(album, { wikiData }) { + const { wikiInfo } = wikiData; - const unbound_trackToListItem = (track, { + const unbound_trackToListItem = ( + track, + { getArtistString, getLinkThemeString, link, language } + ) => { + const itemOpts = { + duration: language.formatDuration(track.duration ?? 0), + track: link.track(track), + }; + return `<li style="${getLinkThemeString(track.color)}">${ + compareArrays( + track.artistContribs.map((c) => c.who), + album.artistContribs.map((c) => c.who), + { checkOrder: false } + ) + ? language.$("trackList.item.withDuration", itemOpts) + : language.$("trackList.item.withDuration.withArtists", { + ...itemOpts, + by: `<span class="by">${language.$( + "trackList.item.withArtists.by", + { + artists: getArtistString(track.artistContribs), + } + )}</span>`, + }) + }</li>`; + }; + + const hasCommentaryEntries = + [album, ...album.tracks].filter((x) => x.commentary).length > 0; + const hasAdditionalFiles = album.additionalFiles?.length > 0; + const albumDuration = getTotalDuration(album.tracks); + + const listTag = getAlbumListTag(album); + + const data = { + type: "data", + path: ["album", album.directory], + data: ({ + serializeContribs, + serializeCover, + serializeGroupsForAlbum, + serializeLink, + }) => ({ + name: album.name, + directory: album.directory, + dates: { + released: album.date, + trackArtAdded: album.trackArtDate, + coverArtAdded: album.coverArtDate, + addedToWiki: album.dateAddedToWiki, + }, + duration: albumDuration, + color: album.color, + cover: serializeCover(album, getAlbumCover), + artistContribs: serializeContribs(album.artistContribs), + coverArtistContribs: serializeContribs(album.coverArtistContribs), + wallpaperArtistContribs: serializeContribs(album.wallpaperArtistContribs), + bannerArtistContribs: serializeContribs(album.bannerArtistContribs), + 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: ({ + fancifyURL, + generateAdditionalFilesShortcut, + generateAdditionalFilesList, + generateChronologyLinks, + generateCoverLink, + getAlbumCover, + getAlbumStylesheet, + getArtistString, + getLinkThemeString, + getSizeOfAdditionalFile, + getThemeString, + link, + language, + transformMultiline, + urls, + }) => { + const trackToListItem = bindOpts(unbound_trackToListItem, { getArtistString, getLinkThemeString, link, - language - }) => { - const itemOpts = { - duration: language.formatDuration(track.duration ?? 0), - track: link.track(track) - }; - return `<li style="${getLinkThemeString(track.color)}">${ - (compareArrays( - track.artistContribs.map(c => c.who), - album.artistContribs.map(c => c.who), - {checkOrder: false}) - ? language.$('trackList.item.withDuration', itemOpts) - : language.$('trackList.item.withDuration.withArtists', { - ...itemOpts, - by: `<span class="by">${ - language.$('trackList.item.withArtists.by', { - artists: getArtistString(track.artistContribs) - }) - }</span>` - })) - }</li>`; - }; - - const hasCommentaryEntries = ([album, ...album.tracks].filter(x => x.commentary).length > 0); - const hasAdditionalFiles = (album.additionalFiles?.length > 0); - const albumDuration = getTotalDuration(album.tracks); - - const listTag = getAlbumListTag(album); - - const data = { - type: 'data', - path: ['album', album.directory], - data: ({ - serializeContribs, - serializeCover, - serializeGroupsForAlbum, - serializeLink - }) => ({ - name: album.name, - directory: album.directory, - dates: { - released: album.date, - trackArtAdded: album.trackArtDate, - coverArtAdded: album.coverArtDate, - addedToWiki: album.dateAddedToWiki - }, - duration: albumDuration, - color: album.color, - cover: serializeCover(album, getAlbumCover), - artistContribs: serializeContribs(album.artistContribs), - coverArtistContribs: serializeContribs(album.coverArtistContribs), - wallpaperArtistContribs: serializeContribs(album.wallpaperArtistContribs), - bannerArtistContribs: serializeContribs(album.bannerArtistContribs), - 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: ({ - fancifyURL, - generateAdditionalFilesShortcut, - generateAdditionalFilesList, - generateChronologyLinks, - generateCoverLink, - getAlbumCover, - getAlbumStylesheet, - getArtistString, - getLinkThemeString, - getSizeOfAdditionalFile, - getThemeString, - link, - language, - transformMultiline, - urls, - }) => { - const trackToListItem = bindOpts(unbound_trackToListItem, { - getArtistString, - getLinkThemeString, - link, - language - }); - - const cover = getAlbumCover(album); - - return { - title: language.$('albumPage.title', {album: album.name}), - stylesheet: getAlbumStylesheet(album), - theme: getThemeString(album.color, [ - `--album-directory: ${album.directory}` - ]), - - banner: album.bannerArtistContribs.length && { - dimensions: album.bannerDimensions, - path: ['media.albumBanner', album.directory, album.bannerFileExtension], - alt: language.$('misc.alt.albumBanner'), - position: 'top' - }, - - main: { - content: fixWS` - ${cover && generateCoverLink({ + language, + }); + + const cover = getAlbumCover(album); + + return { + title: language.$("albumPage.title", { album: album.name }), + stylesheet: getAlbumStylesheet(album), + theme: getThemeString(album.color, [ + `--album-directory: ${album.directory}`, + ]), + + banner: album.bannerArtistContribs.length && { + dimensions: album.bannerDimensions, + path: [ + "media.albumBanner", + album.directory, + album.bannerFileExtension, + ], + alt: language.$("misc.alt.albumBanner"), + position: "top", + }, + + main: { + content: fixWS` + ${ + cover && + generateCoverLink({ src: cover, - alt: language.$('misc.alt.albumCover'), - tags: album.artTags - })} - <h1>${language.$('albumPage.title', {album: album.name})}</h1> + alt: language.$("misc.alt.albumCover"), + tags: album.artTags, + }) + } + <h1>${language.$("albumPage.title", { + album: album.name, + })}</h1> <p> ${[ - album.artistContribs.length && language.$('releaseInfo.by', { - artists: getArtistString(album.artistContribs, { - showContrib: true, - showIcons: true - }) + album.artistContribs.length && + language.$("releaseInfo.by", { + artists: getArtistString( + album.artistContribs, + { + showContrib: true, + showIcons: true, + } + ), }), - album.coverArtistContribs.length && language.$('releaseInfo.coverArtBy', { - artists: getArtistString(album.coverArtistContribs, { - showContrib: true, - showIcons: true - }) + album.coverArtistContribs.length && + language.$("releaseInfo.coverArtBy", { + artists: getArtistString( + album.coverArtistContribs, + { + showContrib: true, + showIcons: true, + } + ), }), - album.wallpaperArtistContribs.length && language.$('releaseInfo.wallpaperArtBy', { - artists: getArtistString(album.wallpaperArtistContribs, { - showContrib: true, - showIcons: true - }) + album.wallpaperArtistContribs.length && + language.$("releaseInfo.wallpaperArtBy", { + artists: getArtistString( + album.wallpaperArtistContribs, + { + showContrib: true, + showIcons: true, + } + ), }), - album.bannerArtistContribs.length && language.$('releaseInfo.bannerArtBy', { - artists: getArtistString(album.bannerArtistContribs, { - showContrib: true, - showIcons: true - }) + album.bannerArtistContribs.length && + language.$("releaseInfo.bannerArtBy", { + artists: getArtistString( + album.bannerArtistContribs, + { + showContrib: true, + showIcons: true, + } + ), }), - album.date && language.$('releaseInfo.released', { - date: language.formatDate(album.date) + album.date && + language.$("releaseInfo.released", { + date: language.formatDate(album.date), }), - (album.coverArtDate && - +album.coverArtDate !== +album.date && - language.$('releaseInfo.artReleased', { - date: language.formatDate(album.coverArtDate) - })), - language.$('releaseInfo.duration', { - duration: language.formatDuration(albumDuration, {approximate: album.tracks.length > 1}) - }) - ].filter(Boolean).join('<br>\n')} + album.coverArtDate && + +album.coverArtDate !== +album.date && + language.$("releaseInfo.artReleased", { + date: language.formatDate(album.coverArtDate), + }), + language.$("releaseInfo.duration", { + duration: language.formatDuration( + albumDuration, + { approximate: album.tracks.length > 1 } + ), + }), + ] + .filter(Boolean) + .join("<br>\n")} </p> - ${(hasAdditionalFiles || hasCommentaryEntries) && fixWS`<p> + ${ + (hasAdditionalFiles || hasCommentaryEntries) && + fixWS`<p> ${[ - hasAdditionalFiles && generateAdditionalFilesShortcut(album.additionalFiles, {language}), - hasCommentaryEntries && language.$('releaseInfo.viewCommentary', { - link: link.albumCommentary(album, { - text: language.$('releaseInfo.viewCommentary.link') - }) - }) - ].filter(Boolean).join('<br>\n') - }</p>`} - ${album.urls?.length && `<p>${ - language.$('releaseInfo.listenOn', { - links: language.formatDisjunctionList(album.urls.map(url => fancifyURL(url, {album: true}))) - }) - }</p>`} - ${album.trackGroups && (album.trackGroups.length > 1 || !album.trackGroups[0].isDefaultTrackGroup) ? fixWS` + hasAdditionalFiles && + generateAdditionalFilesShortcut( + album.additionalFiles, + { language } + ), + hasCommentaryEntries && + language.$("releaseInfo.viewCommentary", { + link: link.albumCommentary(album, { + text: language.$( + "releaseInfo.viewCommentary.link" + ), + }), + }), + ] + .filter(Boolean) + .join("<br>\n")}</p>` + } + ${ + album.urls?.length && + `<p>${language.$("releaseInfo.listenOn", { + links: language.formatDisjunctionList( + album.urls.map((url) => + fancifyURL(url, { album: true }) + ) + ), + })}</p>` + } + ${ + album.trackGroups && + (album.trackGroups.length > 1 || + !album.trackGroups[0].isDefaultTrackGroup) + ? fixWS` <dl class="album-group-list"> - ${album.trackGroups.map(({ name, color, startIndex, tracks }) => fixWS` - <dt>${ - language.$('trackList.section.withDuration', { - duration: language.formatDuration(getTotalDuration(tracks), {approximate: tracks.length > 1}), - section: name - }) - }</dt> - <dd><${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}> - ${tracks.map(trackToListItem).join('\n')} + ${album.trackGroups + .map( + ({ + name, + color, + startIndex, + tracks, + }) => fixWS` + <dt>${language.$( + "trackList.section.withDuration", + { + duration: language.formatDuration( + getTotalDuration(tracks), + { approximate: tracks.length > 1 } + ), + section: name, + } + )}</dt> + <dd><${ + listTag === "ol" + ? `ol start="${startIndex + 1}"` + : listTag + }> + ${tracks + .map(trackToListItem) + .join("\n")} </${listTag}></dd> - `).join('\n')} + ` + ) + .join("\n")} </dl> - ` : fixWS` + ` + : fixWS` <${listTag}> - ${album.tracks.map(trackToListItem).join('\n')} + ${album.tracks.map(trackToListItem).join("\n")} </${listTag}> - `} - ${album.dateAddedToWiki && fixWS` + ` + } + ${ + album.dateAddedToWiki && + fixWS` <p> ${[ - language.$('releaseInfo.addedToWiki', { - date: language.formatDate(album.dateAddedToWiki) - }) - ].filter(Boolean).join('<br>\n')} + language.$("releaseInfo.addedToWiki", { + date: language.formatDate( + album.dateAddedToWiki + ), + }), + ] + .filter(Boolean) + .join("<br>\n")} </p> - `} - ${hasAdditionalFiles && generateAdditionalFilesList(album.additionalFiles, { + ` + } + ${ + hasAdditionalFiles && + generateAdditionalFilesList(album.additionalFiles, { // TODO: Kinda near the metal here... - getFileSize: file => getSizeOfAdditionalFile(urls - .from('media.root') - .to('media.albumAdditionalFile', album.directory, file)), - linkFile: file => link.albumAdditionalFile({album, file}), - })} - ${album.commentary && fixWS` - <p>${language.$('releaseInfo.artistCommentary')}</p> + getFileSize: (file) => + getSizeOfAdditionalFile( + urls + .from("media.root") + .to( + "media.albumAdditionalFile", + album.directory, + file + ) + ), + linkFile: (file) => + link.albumAdditionalFile({ album, file }), + }) + } + ${ + album.commentary && + fixWS` + <p>${language.$("releaseInfo.artistCommentary")}</p> <blockquote> ${transformMultiline(album.commentary)} </blockquote> - `} - ` - }, - - sidebarLeft: generateAlbumSidebar(album, null, { - fancifyURL, - getLinkThemeString, - link, - language, - transformMultiline, - wikiData - }), - - nav: { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - { - html: language.$('albumPage.nav.album', { - album: link.album(album, {class: 'current'}) - }) - }, - ], - bottomRowContent: generateAlbumNavLinks(album, null, {language}), - content: generateAlbumChronologyLinks(album, null, {generateChronologyLinks}), - }, - - secondaryNav: generateAlbumSecondaryNav(album, null, { - language, - link, - getLinkThemeString, - }), - }; - } - }; + ` + } + `, + }, + + sidebarLeft: generateAlbumSidebar(album, null, { + fancifyURL, + getLinkThemeString, + link, + language, + transformMultiline, + wikiData, + }), - return [page, data]; + nav: { + linkContainerClasses: ["nav-links-hierarchy"], + links: [ + { toHome: true }, + { + html: language.$("albumPage.nav.album", { + album: link.album(album, { class: "current" }), + }), + }, + ], + bottomRowContent: generateAlbumNavLinks(album, null, { language }), + content: generateAlbumChronologyLinks(album, null, { + generateChronologyLinks, + }), + }, + + secondaryNav: generateAlbumSecondaryNav(album, null, { + language, + link, + getLinkThemeString, + }), + }; + }, + }; + + return [page, data]; } // Utility functions -export function generateAlbumSidebar(album, currentTrack, { +export function generateAlbumSidebar( + album, + currentTrack, + { fancifyURL, getLinkThemeString, link, language, transformMultiline, - wikiData -}) { - const listTag = getAlbumListTag(album); + wikiData, + } +) { + const listTag = getAlbumListTag(album); - /* + /* const trackGroups = album.trackGroups || [{ name: language.$('albumSidebar.trackList.fallbackGroupName'), color: album.color, @@ -301,185 +398,254 @@ export function generateAlbumSidebar(album, currentTrack, { }]; */ - const { trackGroups } = album; + const { trackGroups } = album; - const trackToListItem = track => html.tag('li', - {class: track === currentTrack && 'current'}, - language.$('albumSidebar.trackList.item', { - track: link.track(track) - })); + const trackToListItem = (track) => + html.tag( + "li", + { class: track === currentTrack && "current" }, + language.$("albumSidebar.trackList.item", { + track: link.track(track), + }) + ); - const nameOrDefault = (isDefaultTrackGroup, name) => - (isDefaultTrackGroup - ? language.$('albumSidebar.trackList.fallbackGroupName') - : name); + const nameOrDefault = (isDefaultTrackGroup, name) => + isDefaultTrackGroup + ? language.$("albumSidebar.trackList.fallbackGroupName") + : name; - const trackListPart = fixWS` + const trackListPart = fixWS` <h1>${link.album(album)}</h1> - ${trackGroups.map(({ name, color, startIndex, tracks, isDefaultTrackGroup }) => - html.tag('details', { + ${trackGroups + .map(({ name, color, startIndex, tracks, isDefaultTrackGroup }) => + 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' - ? language.$('albumSidebar.trackList.group.withRange', { - group: `<span class="group-name">${nameOrDefault(isDefaultTrackGroup, name)}</span>`, - range: `${startIndex + 1}–${startIndex + tracks.length}` - }) - : language.$('albumSidebar.trackList.group', { - group: `<span class="group-name">${nameOrDefault(isDefaultTrackGroup, name)}</span>` - })) + class: tracks.includes(currentTrack) && "current", + }, + [ + html.tag( + "summary", + { style: getLinkThemeString(color) }, + listTag === "ol" + ? language.$("albumSidebar.trackList.group.withRange", { + group: `<span class="group-name">${nameOrDefault( + isDefaultTrackGroup, + name + )}</span>`, + range: `${startIndex + 1}–${ + startIndex + tracks.length + }`, + }) + : language.$("albumSidebar.trackList.group", { + group: `<span class="group-name">${nameOrDefault( + isDefaultTrackGroup, + name + )}</span>`, + }) ), fixWS` - <${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}> - ${tracks.map(trackToListItem).join('\n')} + <${ + listTag === "ol" + ? `ol start="${startIndex + 1}"` + : listTag + }> + ${tracks.map(trackToListItem).join("\n")} </${listTag}> - ` - ])).join('\n')} + `, + ] + ) + ) + .join("\n")} `; - const { groups } = album; - - const groupParts = groups.map(group => { - const albums = group.albums.filter(album => album.date); - const index = albums.indexOf(album); - const next = index >= 0 && albums[index + 1]; - const previous = index > 0 && albums[index - 1]; - return {group, next, previous}; - }).map(({group, next, previous}) => fixWS` - <h1>${ - language.$('albumSidebar.groupBox.title', { - group: link.groupInfo(group) - }) - }</h1> + const { groups } = album; + + const groupParts = groups + .map((group) => { + const albums = group.albums.filter((album) => album.date); + const index = albums.indexOf(album); + const next = index >= 0 && albums[index + 1]; + const previous = index > 0 && albums[index - 1]; + return { group, next, previous }; + }) + .map( + ({ group, next, previous }) => fixWS` + <h1>${language.$("albumSidebar.groupBox.title", { + group: link.groupInfo(group), + })}</h1> ${!currentTrack && transformMultiline(group.descriptionShort)} - ${group.urls?.length && `<p>${ - language.$('releaseInfo.visitOn', { - links: language.formatDisjunctionList(group.urls.map(url => fancifyURL(url))) - }) - }</p>`} - ${!currentTrack && fixWS` - ${next && `<p class="group-chronology-link">${ - language.$('albumSidebar.groupBox.next', { - album: link.album(next) - }) - }</p>`} - ${previous && `<p class="group-chronology-link">${ - language.$('albumSidebar.groupBox.previous', { - album: link.album(previous) - }) - }</p>`} - `} - `); - - if (groupParts.length) { - if (currentTrack) { - const combinedGroupPart = groupParts.join('\n<hr>\n'); - return { - multiple: [ - trackListPart, - combinedGroupPart - ] - }; - } else { - return { - multiple: [ - ...groupParts, - trackListPart - ] - }; + ${ + group.urls?.length && + `<p>${language.$("releaseInfo.visitOn", { + links: language.formatDisjunctionList( + group.urls.map((url) => fancifyURL(url)) + ), + })}</p>` + } + ${ + !currentTrack && + fixWS` + ${ + next && + `<p class="group-chronology-link">${language.$( + "albumSidebar.groupBox.next", + { + album: link.album(next), + } + )}</p>` + } + ${ + previous && + `<p class="group-chronology-link">${language.$( + "albumSidebar.groupBox.previous", + { + album: link.album(previous), + } + )}</p>` + } + ` } + ` + ); + + if (groupParts.length) { + if (currentTrack) { + const combinedGroupPart = groupParts.join("\n<hr>\n"); + return { + multiple: [trackListPart, combinedGroupPart], + }; } else { - return { - content: trackListPart - }; + return { + multiple: [...groupParts, trackListPart], + }; } + } else { + return { + content: trackListPart, + }; + } } -export function generateAlbumSecondaryNav(album, currentTrack, { - link, - language, - getLinkThemeString, -}) { - const { groups } = album; - - if (!groups.length) { - return null; - } - - const groupParts = groups.map(group => { - const albums = group.albums.filter(album => album.date); - const index = albums.indexOf(album); - const next = index >= 0 && albums[index + 1]; - const previous = index > 0 && albums[index - 1]; - return {group, next, previous}; - }).map(({group, next, previous}) => { - const previousNext = !currentTrack && [ - previous && link.album(previous, {color: false, text: language.$('misc.nav.previous')}), - next && link.album(next, {color: false, text: language.$('misc.nav.next')}) - ].filter(Boolean); - return html.tag('span', {style: getLinkThemeString(group.color)}, [ - language.$('albumSidebar.groupBox.title', { - group: link.groupInfo(group) +export function generateAlbumSecondaryNav( + album, + currentTrack, + { link, language, getLinkThemeString } +) { + const { groups } = album; + + if (!groups.length) { + return null; + } + + const groupParts = groups + .map((group) => { + const albums = group.albums.filter((album) => album.date); + const index = albums.indexOf(album); + const next = index >= 0 && albums[index + 1]; + const previous = index > 0 && albums[index - 1]; + return { group, next, previous }; + }) + .map(({ group, next, previous }) => { + const previousNext = + !currentTrack && + [ + previous && + link.album(previous, { + color: false, + text: language.$("misc.nav.previous"), + }), + next && + link.album(next, { + color: false, + text: language.$("misc.nav.next"), }), - previousNext?.length && `(${previousNext.join(',\n')})` - ]); + ].filter(Boolean); + return html.tag("span", { style: getLinkThemeString(group.color) }, [ + language.$("albumSidebar.groupBox.title", { + group: link.groupInfo(group), + }), + previousNext?.length && `(${previousNext.join(",\n")})`, + ]); }); - return { - classes: ['dot-between-spans'], - content: groupParts.join('\n'), - }; + return { + classes: ["dot-between-spans"], + content: groupParts.join("\n"), + }; } -export function generateAlbumNavLinks(album, currentTrack, { - generatePreviousNextLinks, - language -}) { - if (album.tracks.length <= 1) { - return ''; - } - - const previousNextLinks = currentTrack && generatePreviousNextLinks(currentTrack, { - data: album.tracks, - linkKey: 'track' +export function generateAlbumNavLinks( + album, + currentTrack, + { generatePreviousNextLinks, language } +) { + if (album.tracks.length <= 1) { + return ""; + } + + const previousNextLinks = + currentTrack && + generatePreviousNextLinks(currentTrack, { + data: album.tracks, + linkKey: "track", }); - const randomLink = `<a href="#" data-random="track-in-album" id="random-button">${ - (currentTrack - ? language.$('trackPage.nav.random') - : language.$('albumPage.nav.randomTrack')) - }</a>`; - - return (previousNextLinks - ? `(${previousNextLinks}<span class="js-hide-until-data">, ${randomLink}</span>)` - : `<span class="js-hide-until-data">(${randomLink})</span>`); + const randomLink = `<a href="#" data-random="track-in-album" id="random-button">${ + currentTrack + ? language.$("trackPage.nav.random") + : language.$("albumPage.nav.randomTrack") + }</a>`; + + return previousNextLinks + ? `(${previousNextLinks}<span class="js-hide-until-data">, ${randomLink}</span>)` + : `<span class="js-hide-until-data">(${randomLink})</span>`; } -export function generateAlbumChronologyLinks(album, currentTrack, {generateChronologyLinks}) { - return html.tag('div', { - [html.onlyIfContent]: true, - class: 'nav-chronology-links', - }, [ - currentTrack && generateChronologyLinks(currentTrack, { - contribKey: 'artistContribs', - getThings: artist => [...artist.tracksAsArtist, ...artist.tracksAsContributor], - headingString: 'misc.chronology.heading.track' +export function generateAlbumChronologyLinks( + album, + currentTrack, + { generateChronologyLinks } +) { + return html.tag( + "div", + { + [html.onlyIfContent]: true, + class: "nav-chronology-links", + }, + [ + currentTrack && + generateChronologyLinks(currentTrack, { + contribKey: "artistContribs", + getThings: (artist) => [ + ...artist.tracksAsArtist, + ...artist.tracksAsContributor, + ], + headingString: "misc.chronology.heading.track", }), - currentTrack && generateChronologyLinks(currentTrack, { - contribKey: 'contributorContribs', - getThings: artist => [...artist.tracksAsArtist, ...artist.tracksAsContributor], - headingString: 'misc.chronology.heading.track' + currentTrack && + generateChronologyLinks(currentTrack, { + contribKey: "contributorContribs", + getThings: (artist) => [ + ...artist.tracksAsArtist, + ...artist.tracksAsContributor, + ], + headingString: "misc.chronology.heading.track", }), - generateChronologyLinks(currentTrack || album, { - contribKey: 'coverArtistContribs', - dateKey: 'coverArtDate', - getThings: artist => [...artist.albumsAsCoverArtist, ...artist.tracksAsCoverArtist], - headingString: 'misc.chronology.heading.coverArt' - }) - ].filter(Boolean).join('\n')); + generateChronologyLinks(currentTrack || album, { + contribKey: "coverArtistContribs", + dateKey: "coverArtDate", + getThings: (artist) => [ + ...artist.albumsAsCoverArtist, + ...artist.tracksAsCoverArtist, + ], + headingString: "misc.chronology.heading.coverArt", + }), + ] + .filter(Boolean) + .join("\n") + ); } diff --git a/src/page/artist-alias.js b/src/page/artist-alias.js index ac23e902..4fc129e9 100644 --- a/src/page/artist-alias.js +++ b/src/page/artist-alias.js @@ -1,22 +1,21 @@ // Artist alias redirect pages. // (Makes old permalinks bring visitors to the up-to-date page.) -export function targets({wikiData}) { - return wikiData.artistAliasData; +export function targets({ wikiData }) { + return wikiData.artistAliasData; } -export function write(aliasArtist, {wikiData}) { - // This function doesn't actually use wikiData, 8ut, um, consistency? +export function write(aliasArtist, { wikiData }) { + // This function doesn't actually use wikiData, 8ut, um, consistency? - const { aliasedArtist } = aliasArtist; + const { aliasedArtist } = aliasArtist; - const redirect = { - type: 'redirect', - fromPath: ['artist', aliasArtist.directory], - toPath: ['artist', aliasedArtist.directory], - title: () => aliasedArtist.name - }; + const redirect = { + type: "redirect", + fromPath: ["artist", aliasArtist.directory], + toPath: ["artist", aliasedArtist.directory], + title: () => aliasedArtist.name, + }; - return [redirect]; + return [redirect]; } - diff --git a/src/page/artist.js b/src/page/artist.js index 6c31a010..8be20106 100644 --- a/src/page/artist.js +++ b/src/page/artist.js @@ -4,515 +4,753 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; -import * as html from '../util/html.js'; +import * as html from "../util/html.js"; -import { - bindOpts, - unique -} from '../util/sugar.js'; +import { bindOpts, unique } from "../util/sugar.js"; import { - chunkByProperties, - getTotalDuration, - sortAlbumsTracksChronologically, - sortByDate, - sortByDirectory, - sortChronologically, -} from '../util/wiki-data.js'; + chunkByProperties, + getTotalDuration, + sortAlbumsTracksChronologically, + sortByDate, + sortByDirectory, + sortChronologically, +} from "../util/wiki-data.js"; // Page exports -export function targets({wikiData}) { - return wikiData.artistData; +export function targets({ wikiData }) { + return wikiData.artistData; } -export function write(artist, {wikiData}) { - const { groupData, wikiInfo } = wikiData; - - const { name, urls, contextNotes } = artist; - - const artThingsAll = sortAlbumsTracksChronologically(unique([ - ...artist.albumsAsCoverArtist ?? [], - ...artist.albumsAsWallpaperArtist ?? [], - ...artist.albumsAsBannerArtist ?? [], - ...artist.tracksAsCoverArtist ?? [] - ]), {getDate: o => o.coverArtDate}); - - const artThingsGallery = sortAlbumsTracksChronologically([ - ...artist.albumsAsCoverArtist ?? [], - ...artist.tracksAsCoverArtist ?? [] - ], {getDate: o => o.coverArtDate}); - - const commentaryThings = sortAlbumsTracksChronologically([ - ...artist.albumsAsCommentator ?? [], - ...artist.tracksAsCommentator ?? [] - ]); - - const hasGallery = artThingsGallery.length > 0; - - const getArtistsAndContrib = (thing, key) => ({ - artists: thing[key]?.filter(({ who }) => who !== artist), - contrib: thing[key]?.find(({ who }) => who === artist), - thing, - key - }); - - const artListChunks = chunkByProperties(artThingsAll.flatMap(thing => - (['coverArtistContribs', 'wallpaperArtistContribs', 'bannerArtistContribs'] - .map(key => getArtistsAndContrib(thing, key)) - .filter(({ contrib }) => contrib) - .map(props => ({ - album: thing.album || thing, - track: thing.album ? thing : null, - date: thing.date, - ...props - }))) - ), ['date', 'album']); - - const commentaryListChunks = chunkByProperties(commentaryThings.map(thing => ({ - album: thing.album || thing, - track: thing.album ? thing : null - })), ['album']); - - const allTracks = sortAlbumsTracksChronologically(unique([ - ...artist.tracksAsArtist ?? [], - ...artist.tracksAsContributor ?? [] - ])); - - const chunkTracks = tracks => ( - chunkByProperties(tracks.map(track => ({ - track, - date: +track.date, - album: track.album, - duration: track.duration, - artists: (track.artistContribs.some(({ who }) => who === artist) - ? track.artistContribs.filter(({ who }) => who !== artist) - : track.contributorContribs.filter(({ who }) => who !== artist)), - contrib: { - who: artist, - whatArray: [ - track.artistContribs.find(({ who }) => who === artist)?.what, - track.contributorContribs.find(({ who }) => who === artist)?.what - ].filter(Boolean) +export function write(artist, { wikiData }) { + const { groupData, wikiInfo } = wikiData; + + const { name, urls, contextNotes } = artist; + + const artThingsAll = sortAlbumsTracksChronologically( + unique([ + ...(artist.albumsAsCoverArtist ?? []), + ...(artist.albumsAsWallpaperArtist ?? []), + ...(artist.albumsAsBannerArtist ?? []), + ...(artist.tracksAsCoverArtist ?? []), + ]), + { getDate: (o) => o.coverArtDate } + ); + + const artThingsGallery = sortAlbumsTracksChronologically( + [ + ...(artist.albumsAsCoverArtist ?? []), + ...(artist.tracksAsCoverArtist ?? []), + ], + { getDate: (o) => o.coverArtDate } + ); + + const commentaryThings = sortAlbumsTracksChronologically([ + ...(artist.albumsAsCommentator ?? []), + ...(artist.tracksAsCommentator ?? []), + ]); + + const hasGallery = artThingsGallery.length > 0; + + const getArtistsAndContrib = (thing, key) => ({ + artists: thing[key]?.filter(({ who }) => who !== artist), + contrib: thing[key]?.find(({ who }) => who === artist), + thing, + key, + }); + + const artListChunks = chunkByProperties( + artThingsAll.flatMap((thing) => + ["coverArtistContribs", "wallpaperArtistContribs", "bannerArtistContribs"] + .map((key) => getArtistsAndContrib(thing, key)) + .filter(({ contrib }) => contrib) + .map((props) => ({ + album: thing.album || thing, + track: thing.album ? thing : null, + date: thing.date, + ...props, + })) + ), + ["date", "album"] + ); + + const commentaryListChunks = chunkByProperties( + commentaryThings.map((thing) => ({ + album: thing.album || thing, + track: thing.album ? thing : null, + })), + ["album"] + ); + + const allTracks = sortAlbumsTracksChronologically( + unique([ + ...(artist.tracksAsArtist ?? []), + ...(artist.tracksAsContributor ?? []), + ]) + ); + + const chunkTracks = (tracks) => + chunkByProperties( + tracks.map((track) => ({ + track, + date: +track.date, + album: track.album, + duration: track.duration, + artists: track.artistContribs.some(({ who }) => who === artist) + ? track.artistContribs.filter(({ who }) => who !== artist) + : track.contributorContribs.filter(({ who }) => who !== artist), + contrib: { + who: artist, + whatArray: [ + track.artistContribs.find(({ who }) => who === artist)?.what, + track.contributorContribs.find(({ who }) => who === artist)?.what, + ].filter(Boolean), + }, + })), + ["date", "album"] + ).map(({ date, album, chunk }) => ({ + date, + album, + chunk, + duration: getTotalDuration(chunk), + })); + + const trackListChunks = chunkTracks(allTracks); + const totalDuration = getTotalDuration(allTracks); + + const countGroups = (things) => { + const usedGroups = things.flatMap( + (thing) => thing.groups || thing.album?.groups || [] + ); + return groupData + .map((group) => ({ + group, + contributions: usedGroups.filter((g) => g === group).length, + })) + .filter(({ contributions }) => contributions > 0) + .sort((a, b) => b.contributions - a.contributions); + }; + + const musicGroups = countGroups(allTracks); + const artGroups = countGroups(artThingsAll); + + let flashes, flashListChunks; + if (wikiInfo.enableFlashesAndGames) { + flashes = sortChronologically(artist.flashesAsContributor?.slice() ?? []); + flashListChunks = chunkByProperties( + flashes.map((flash) => ({ + act: flash.act, + flash, + date: flash.date, + // Manual artists/contrib properties here, 8ecause we don't + // want to show the full list of other contri8utors inline. + // (It can often 8e very, very large!) + artists: [], + contrib: flash.contributorContribs.find(({ who }) => who === artist), + })), + ["act"] + ).map(({ act, chunk }) => ({ + act, + chunk, + dateFirst: chunk[0].date, + dateLast: chunk[chunk.length - 1].date, + })); + } + + const generateEntryAccents = ({ + getArtistString, + language, + original, + entry, + artists, + contrib, + }) => + original + ? language.$("artistPage.creditList.entry.rerelease", { entry }) + : artists.length + ? contrib.what || contrib.whatArray?.length + ? language.$( + "artistPage.creditList.entry.withArtists.withContribution", + { + entry, + artists: getArtistString(artists), + contribution: contrib.whatArray + ? language.formatUnitList(contrib.whatArray) + : contrib.what, } - })), ['date', 'album']) - .map(({date, album, chunk}) => ({ - date, album, chunk, - duration: getTotalDuration(chunk), - }))); - - const trackListChunks = chunkTracks(allTracks); - const totalDuration = getTotalDuration(allTracks); - - const countGroups = things => { - const usedGroups = things.flatMap(thing => thing.groups || thing.album?.groups || []); - return groupData - .map(group => ({ - group, - contributions: usedGroups.filter(g => g === group).length - })) - .filter(({ contributions }) => contributions > 0) - .sort((a, b) => b.contributions - a.contributions); - }; + ) + : language.$("artistPage.creditList.entry.withArtists", { + entry, + artists: getArtistString(artists), + }) + : contrib.what || contrib.whatArray?.length + ? language.$("artistPage.creditList.entry.withContribution", { + entry, + contribution: contrib.whatArray + ? language.formatUnitList(contrib.whatArray) + : contrib.what, + }) + : entry; - const musicGroups = countGroups(allTracks); - const artGroups = countGroups(artThingsAll); - - let flashes, flashListChunks; - if (wikiInfo.enableFlashesAndGames) { - flashes = sortChronologically(artist.flashesAsContributor?.slice() ?? []); - flashListChunks = ( - chunkByProperties(flashes.map(flash => ({ - act: flash.act, - flash, - date: flash.date, - // Manual artists/contrib properties here, 8ecause we don't - // want to show the full list of other contri8utors inline. - // (It can often 8e very, very large!) - artists: [], - contrib: flash.contributorContribs.find(({ who }) => who === artist) - })), ['act']) - .map(({ act, chunk }) => ({ - act, chunk, - dateFirst: chunk[0].date, - dateLast: chunk[chunk.length - 1].date - }))); - } - - const generateEntryAccents = ({ - getArtistString, language, - original, entry, artists, contrib - }) => - (original - ? language.$('artistPage.creditList.entry.rerelease', {entry}) - : (artists.length - ? ((contrib.what || contrib.whatArray?.length) - ? language.$('artistPage.creditList.entry.withArtists.withContribution', { - entry, - artists: getArtistString(artists), - contribution: (contrib.whatArray ? language.formatUnitList(contrib.whatArray) : contrib.what) - }) - : language.$('artistPage.creditList.entry.withArtists', { - entry, - artists: getArtistString(artists) - })) - : ((contrib.what || contrib.whatArray?.length) - ? language.$('artistPage.creditList.entry.withContribution', { - entry, - contribution: (contrib.whatArray ? language.formatUnitList(contrib.whatArray) : contrib.what) - }) - : entry))); - - const unbound_generateTrackList = (chunks, { - getArtistString, link, language - }) => fixWS` + const unbound_generateTrackList = ( + chunks, + { getArtistString, link, language } + ) => fixWS` <dl> - ${chunks.map(({date, album, chunk, duration}) => fixWS` + ${chunks + .map( + ({ date, album, chunk, duration }) => fixWS` <dt>${ - (date && duration) ? language.$('artistPage.creditList.album.withDate.withDuration', { + date && duration + ? language.$( + "artistPage.creditList.album.withDate.withDuration", + { + album: link.album(album), + date: language.formatDate(date), + duration: language.formatDuration(duration, { + approximate: true, + }), + } + ) + : date + ? language.$("artistPage.creditList.album.withDate", { album: link.album(album), date: language.formatDate(date), - duration: language.formatDuration(duration, {approximate: true}) - }) : date ? language.$('artistPage.creditList.album.withDate', { + }) + : duration + ? language.$("artistPage.creditList.album.withDuration", { album: link.album(album), - date: language.formatDate(date) - }) : duration ? language.$('artistPage.creditList.album.withDuration', { + duration: language.formatDuration(duration, { + approximate: true, + }), + }) + : language.$("artistPage.creditList.album", { album: link.album(album), - duration: language.formatDuration(duration, {approximate: true}) - }) : language.$('artistPage.creditList.album', { - album: link.album(album) - })}</dt> + }) + }</dt> <dd><ul> - ${(chunk - .map(({track, ...props}) => ({ - original: track.originalReleaseTrack, - entry: language.$('artistPage.creditList.entry.track.withDuration', { - track: link.track(track), - duration: language.formatDuration(track.duration ?? 0) - }), - ...props - })) - .map(({original, ...opts}) => html.tag('li', - {class: original && 'rerelease'}, - generateEntryAccents({getArtistString, language, original, ...opts}))) - .join('\n'))} + ${chunk + .map(({ track, ...props }) => ({ + original: track.originalReleaseTrack, + entry: language.$( + "artistPage.creditList.entry.track.withDuration", + { + track: link.track(track), + duration: language.formatDuration( + track.duration ?? 0 + ), + } + ), + ...props, + })) + .map(({ original, ...opts }) => + html.tag( + "li", + { class: original && "rerelease" }, + generateEntryAccents({ + getArtistString, + language, + original, + ...opts, + }) + ) + ) + .join("\n")} </ul></dd> - `).join('\n')} + ` + ) + .join("\n")} </dl> `; - const unbound_serializeArtistsAndContrib = (key, { - serializeContribs, - serializeLink - }) => thing => { - const { artists, contrib } = getArtistsAndContrib(thing, key); - const ret = {}; - ret.link = serializeLink(thing); - if (contrib.what) ret.contribution = contrib.what; - if (artists.length) ret.otherArtists = serializeContribs(artists); - return ret; + const unbound_serializeArtistsAndContrib = + (key, { serializeContribs, serializeLink }) => + (thing) => { + const { artists, contrib } = getArtistsAndContrib(thing, key); + const ret = {}; + ret.link = serializeLink(thing); + if (contrib.what) ret.contribution = contrib.what; + if (artists.length) ret.otherArtists = serializeContribs(artists); + return ret; }; - const unbound_serializeTrackListChunks = (chunks, {serializeLink}) => - chunks.map(({date, album, chunk, duration}) => ({ - album: serializeLink(album), - date, - duration, - tracks: chunk.map(({ track }) => ({ - link: serializeLink(track), - duration: track.duration - })) - })); - - const data = { - type: 'data', - path: ['artist', artist.directory], - data: ({ - serializeContribs, - serializeLink - }) => { - const serializeArtistsAndContrib = bindOpts(unbound_serializeArtistsAndContrib, { - serializeContribs, - serializeLink - }); - - const serializeTrackListChunks = bindOpts(unbound_serializeTrackListChunks, { - serializeLink - }); - - return { - albums: { - asCoverArtist: artist.albumsAsCoverArtist?.map(serializeArtistsAndContrib('coverArtistContribs')), - asWallpaperArtist: artist.albumsAsWallpaperArtist?.map(serializeArtistsAndContrib('wallpaperArtistContribs')), - asBannerArtist: artist.albumsAsBannerArtist?.map(serializeArtistsAndContrib('bannerArtistContribs')) - }, - flashes: wikiInfo.enableFlashesAndGames ? { - asContributor: (artist.flashesAsContributor - ?.map(flash => getArtistsAndContrib(flash, 'contributorContribs')) - .map(({ contrib, thing: flash }) => ({ - link: serializeLink(flash), - contribution: contrib.what - }))) - } : null, - tracks: { - asArtist: artist.tracksAsArtist.map(serializeArtistsAndContrib('artistContribs')), - asContributor: artist.tracksAsContributor.map(serializeArtistsAndContrib('contributorContribs')), - chunked: serializeTrackListChunks(trackListChunks) - } - }; + const unbound_serializeTrackListChunks = (chunks, { serializeLink }) => + chunks.map(({ date, album, chunk, duration }) => ({ + album: serializeLink(album), + date, + duration, + tracks: chunk.map(({ track }) => ({ + link: serializeLink(track), + duration: track.duration, + })), + })); + + const data = { + type: "data", + path: ["artist", artist.directory], + data: ({ serializeContribs, serializeLink }) => { + const serializeArtistsAndContrib = bindOpts( + unbound_serializeArtistsAndContrib, + { + serializeContribs, + serializeLink, } - }; + ); - const infoPage = { - type: 'page', - path: ['artist', artist.directory], - page: ({ - fancifyURL, - generateCoverLink, - generateInfoGalleryLinks, - getArtistAvatar, - getArtistString, - link, - language, - to, - transformMultiline - }) => { - const generateTrackList = bindOpts(unbound_generateTrackList, { - getArtistString, - link, - language - }); - - return { - title: language.$('artistPage.title', {artist: name}), - - main: { - content: fixWS` - ${artist.hasAvatar && generateCoverLink({ + const serializeTrackListChunks = bindOpts( + unbound_serializeTrackListChunks, + { + serializeLink, + } + ); + + return { + albums: { + asCoverArtist: artist.albumsAsCoverArtist?.map( + serializeArtistsAndContrib("coverArtistContribs") + ), + asWallpaperArtist: artist.albumsAsWallpaperArtist?.map( + serializeArtistsAndContrib("wallpaperArtistContribs") + ), + asBannerArtist: artist.albumsAsBannerArtist?.map( + serializeArtistsAndContrib("bannerArtistContribs") + ), + }, + flashes: wikiInfo.enableFlashesAndGames + ? { + asContributor: artist.flashesAsContributor + ?.map((flash) => + getArtistsAndContrib(flash, "contributorContribs") + ) + .map(({ contrib, thing: flash }) => ({ + link: serializeLink(flash), + contribution: contrib.what, + })), + } + : null, + tracks: { + asArtist: artist.tracksAsArtist.map( + serializeArtistsAndContrib("artistContribs") + ), + asContributor: artist.tracksAsContributor.map( + serializeArtistsAndContrib("contributorContribs") + ), + chunked: serializeTrackListChunks(trackListChunks), + }, + }; + }, + }; + + const infoPage = { + type: "page", + path: ["artist", artist.directory], + page: ({ + fancifyURL, + generateCoverLink, + generateInfoGalleryLinks, + getArtistAvatar, + getArtistString, + link, + language, + to, + transformMultiline, + }) => { + const generateTrackList = bindOpts(unbound_generateTrackList, { + getArtistString, + link, + language, + }); + + return { + title: language.$("artistPage.title", { artist: name }), + + main: { + content: fixWS` + ${ + artist.hasAvatar && + generateCoverLink({ src: getArtistAvatar(artist), - alt: language.$('misc.alt.artistAvatar') - })} - <h1>${language.$('artistPage.title', {artist: name})}</h1> - ${contextNotes && fixWS` - <p>${language.$('releaseInfo.note')}</p> + alt: language.$("misc.alt.artistAvatar"), + }) + } + <h1>${language.$("artistPage.title", { + artist: name, + })}</h1> + ${ + contextNotes && + fixWS` + <p>${language.$("releaseInfo.note")}</p> <blockquote> ${transformMultiline(contextNotes)} </blockquote> <hr> - `} - ${urls?.length && `<p>${language.$('releaseInfo.visitOn', { - links: language.formatDisjunctionList(urls.map(url => fancifyURL(url, {language}))) - })}</p>`} - ${hasGallery && `<p>${language.$('artistPage.viewArtGallery', { + ` + } + ${ + urls?.length && + `<p>${language.$("releaseInfo.visitOn", { + links: language.formatDisjunctionList( + urls.map((url) => fancifyURL(url, { language })) + ), + })}</p>` + } + ${ + hasGallery && + `<p>${language.$("artistPage.viewArtGallery", { link: link.artistGallery(artist, { - text: language.$('artistPage.viewArtGallery.link') - }) - })}</p>`} - <p>${language.$('misc.jumpTo.withLinks', { - links: language.formatUnitList([ - allTracks.length && `<a href="#tracks">${language.$('artistPage.trackList.title')}</a>`, - artThingsAll.length && `<a href="#art">${language.$('artistPage.artList.title')}</a>`, - wikiInfo.enableFlashesAndGames && flashes.length && `<a href="#flashes">${language.$('artistPage.flashList.title')}</a>`, - commentaryThings.length && `<a href="#commentary">${language.$('artistPage.commentaryList.title')}</a>` - ].filter(Boolean)) + text: language.$( + "artistPage.viewArtGallery.link" + ), + }), + })}</p>` + } + <p>${language.$("misc.jumpTo.withLinks", { + links: language.formatUnitList( + [ + allTracks.length && + `<a href="#tracks">${language.$( + "artistPage.trackList.title" + )}</a>`, + artThingsAll.length && + `<a href="#art">${language.$( + "artistPage.artList.title" + )}</a>`, + wikiInfo.enableFlashesAndGames && + flashes.length && + `<a href="#flashes">${language.$( + "artistPage.flashList.title" + )}</a>`, + commentaryThings.length && + `<a href="#commentary">${language.$( + "artistPage.commentaryList.title" + )}</a>`, + ].filter(Boolean) + ), })}</p> - ${allTracks.length && fixWS` - <h2 id="tracks">${language.$('artistPage.trackList.title')}</h2> - <p>${language.$('artistPage.contributedDurationLine', { + ${ + allTracks.length && + fixWS` + <h2 id="tracks">${language.$( + "artistPage.trackList.title" + )}</h2> + <p>${language.$( + "artistPage.contributedDurationLine", + { artist: artist.name, - duration: language.formatDuration(totalDuration, {approximate: true, unit: true}) - })}</p> - <p>${language.$('artistPage.musicGroupsLine', { - groups: language.formatUnitList(musicGroups - .map(({ group, contributions }) => language.$('artistPage.groupsLine.item', { - group: link.groupInfo(group), - contributions: language.countContributions(contributions) - }))) + duration: language.formatDuration( + totalDuration, + { approximate: true, unit: true } + ), + } + )}</p> + <p>${language.$("artistPage.musicGroupsLine", { + groups: language.formatUnitList( + musicGroups.map(({ group, contributions }) => + language.$("artistPage.groupsLine.item", { + group: link.groupInfo(group), + contributions: + language.countContributions( + contributions + ), + }) + ) + ), })}</p> ${generateTrackList(trackListChunks)} - `} - ${artThingsAll.length && fixWS` - <h2 id="art">${language.$('artistPage.artList.title')}</h2> - ${hasGallery && `<p>${language.$('artistPage.viewArtGallery.orBrowseList', { - link: link.artistGallery(artist, { - text: language.$('artistPage.viewArtGallery.link') - }) - })}</p>`} - <p>${language.$('artistPage.artGroupsLine', { - groups: language.formatUnitList(artGroups - .map(({ group, contributions }) => language.$('artistPage.groupsLine.item', { - group: link.groupInfo(group), - contributions: language.countContributions(contributions) - }))) + ` + } + ${ + artThingsAll.length && + fixWS` + <h2 id="art">${language.$( + "artistPage.artList.title" + )}</h2> + ${ + hasGallery && + `<p>${language.$( + "artistPage.viewArtGallery.orBrowseList", + { + link: link.artistGallery(artist, { + text: language.$( + "artistPage.viewArtGallery.link" + ), + }), + } + )}</p>` + } + <p>${language.$("artistPage.artGroupsLine", { + groups: language.formatUnitList( + artGroups.map(({ group, contributions }) => + language.$("artistPage.groupsLine.item", { + group: link.groupInfo(group), + contributions: + language.countContributions( + contributions + ), + }) + ) + ), })}</p> <dl> - ${artListChunks.map(({date, album, chunk}) => fixWS` - <dt>${language.$('artistPage.creditList.album.withDate', { + ${artListChunks + .map( + ({ date, album, chunk }) => fixWS` + <dt>${language.$( + "artistPage.creditList.album.withDate", + { album: link.album(album), - date: language.formatDate(date) - })}</dt> + date: language.formatDate(date), + } + )}</dt> <dd><ul> - ${(chunk - .map(({album, track, key, ...props}) => ({ - entry: (track - ? language.$('artistPage.creditList.entry.track', { - track: link.track(track) - }) - : `<i>${language.$('artistPage.creditList.entry.album.' + { - wallpaperArtistContribs: 'wallpaperArt', - bannerArtistContribs: 'bannerArt', - coverArtistContribs: 'coverArt' - }[key])}</i>`), - ...props - })) - .map(opts => generateEntryAccents({getArtistString, language, ...opts})) - .map(row => `<li>${row}</li>`) - .join('\n'))} + ${chunk + .map( + ({ + album, + track, + key, + ...props + }) => ({ + entry: track + ? language.$( + "artistPage.creditList.entry.track", + { + track: link.track(track), + } + ) + : `<i>${language.$( + "artistPage.creditList.entry.album." + + { + wallpaperArtistContribs: + "wallpaperArt", + bannerArtistContribs: + "bannerArt", + coverArtistContribs: + "coverArt", + }[key] + )}</i>`, + ...props, + }) + ) + .map((opts) => + generateEntryAccents({ + getArtistString, + language, + ...opts, + }) + ) + .map((row) => `<li>${row}</li>`) + .join("\n")} </ul></dd> - `).join('\n')} + ` + ) + .join("\n")} </dl> - `} - ${wikiInfo.enableFlashesAndGames && flashes.length && fixWS` - <h2 id="flashes">${language.$('artistPage.flashList.title')}</h2> + ` + } + ${ + wikiInfo.enableFlashesAndGames && + flashes.length && + fixWS` + <h2 id="flashes">${language.$( + "artistPage.flashList.title" + )}</h2> <dl> - ${flashListChunks.map(({act, chunk, dateFirst, dateLast}) => fixWS` - <dt>${language.$('artistPage.creditList.flashAct.withDateRange', { - act: link.flash(chunk[0].flash, {text: act.name}), - dateRange: language.formatDateRange(dateFirst, dateLast) - })}</dt> + ${flashListChunks + .map( + ({ + act, + chunk, + dateFirst, + dateLast, + }) => fixWS` + <dt>${language.$( + "artistPage.creditList.flashAct.withDateRange", + { + act: link.flash(chunk[0].flash, { + text: act.name, + }), + dateRange: language.formatDateRange( + dateFirst, + dateLast + ), + } + )}</dt> <dd><ul> - ${(chunk - .map(({flash, ...props}) => ({ - entry: language.$('artistPage.creditList.entry.flash', { - flash: link.flash(flash) - }), - ...props - })) - .map(opts => generateEntryAccents({getArtistString, language, ...opts})) - .map(row => `<li>${row}</li>`) - .join('\n'))} + ${chunk + .map(({ flash, ...props }) => ({ + entry: language.$( + "artistPage.creditList.entry.flash", + { + flash: link.flash(flash), + } + ), + ...props, + })) + .map((opts) => + generateEntryAccents({ + getArtistString, + language, + ...opts, + }) + ) + .map((row) => `<li>${row}</li>`) + .join("\n")} </ul></dd> - `).join('\n')} + ` + ) + .join("\n")} </dl> - `} - ${commentaryThings.length && fixWS` - <h2 id="commentary">${language.$('artistPage.commentaryList.title')}</h2> + ` + } + ${ + commentaryThings.length && + fixWS` + <h2 id="commentary">${language.$( + "artistPage.commentaryList.title" + )}</h2> <dl> - ${commentaryListChunks.map(({album, chunk}) => fixWS` - <dt>${language.$('artistPage.creditList.album', { - album: link.album(album) - })}</dt> + ${commentaryListChunks + .map( + ({ album, chunk }) => fixWS` + <dt>${language.$( + "artistPage.creditList.album", + { + album: link.album(album), + } + )}</dt> <dd><ul> - ${(chunk - .map(({album, track, ...props}) => track - ? language.$('artistPage.creditList.entry.track', { - track: link.track(track) - }) - : `<i>${language.$('artistPage.creditList.entry.album.commentary')}</i>`) - .map(row => `<li>${row}</li>`) - .join('\n'))} + ${chunk + .map(({ album, track, ...props }) => + track + ? language.$( + "artistPage.creditList.entry.track", + { + track: link.track(track), + } + ) + : `<i>${language.$( + "artistPage.creditList.entry.album.commentary" + )}</i>` + ) + .map((row) => `<li>${row}</li>`) + .join("\n")} </ul></dd> - `).join('\n')} + ` + ) + .join("\n")} </dl> - `} - ` - }, - - nav: generateNavForArtist(artist, false, hasGallery, { - generateInfoGalleryLinks, - link, - language, - wikiData - }) - }; - } - }; - - const galleryPage = hasGallery && { - type: 'page', - path: ['artistGallery', artist.directory], - page: ({ - generateInfoGalleryLinks, - getAlbumCover, - getGridHTML, - getTrackCover, - link, - language, - to - }) => ({ - title: language.$('artistGalleryPage.title', {artist: name}), - - main: { - classes: ['top-index'], - content: fixWS` - <h1>${language.$('artistGalleryPage.title', {artist: name})}</h1> - <p class="quick-info">${language.$('artistGalleryPage.infoLine', { - coverArts: language.countCoverArts(artThingsGallery.length, {unit: true}) - })}</p> + ` + } + `, + }, + + nav: generateNavForArtist(artist, false, hasGallery, { + generateInfoGalleryLinks, + link, + language, + wikiData, + }), + }; + }, + }; + + const galleryPage = hasGallery && { + type: "page", + path: ["artistGallery", artist.directory], + page: ({ + generateInfoGalleryLinks, + getAlbumCover, + getGridHTML, + getTrackCover, + link, + language, + to, + }) => ({ + title: language.$("artistGalleryPage.title", { artist: name }), + + main: { + classes: ["top-index"], + content: fixWS` + <h1>${language.$("artistGalleryPage.title", { + artist: name, + })}</h1> + <p class="quick-info">${language.$( + "artistGalleryPage.infoLine", + { + coverArts: language.countCoverArts( + artThingsGallery.length, + { unit: true } + ), + } + )}</p> <div class="grid-listing"> ${getGridHTML({ - entries: artThingsGallery.map(item => ({item})), - srcFn: thing => (thing.album - ? getTrackCover(thing) - : getAlbumCover(thing)), - linkFn: (thing, opts) => (thing.album - ? link.track(thing, opts) - : link.album(thing, opts)) + entries: artThingsGallery.map((item) => ({ item })), + srcFn: (thing) => + thing.album + ? getTrackCover(thing) + : getAlbumCover(thing), + linkFn: (thing, opts) => + thing.album + ? link.track(thing, opts) + : link.album(thing, opts), })} </div> - ` - }, - - nav: generateNavForArtist(artist, true, hasGallery, { - generateInfoGalleryLinks, - link, - language, - wikiData - }) - }) - }; - - return [data, infoPage, galleryPage].filter(Boolean); + `, + }, + + nav: generateNavForArtist(artist, true, hasGallery, { + generateInfoGalleryLinks, + link, + language, + wikiData, + }), + }), + }; + + return [data, infoPage, galleryPage].filter(Boolean); } // Utility functions -function generateNavForArtist(artist, isGallery, hasGallery, { - generateInfoGalleryLinks, - link, - language, - wikiData -}) { - const { wikiInfo } = wikiData; - - const infoGalleryLinks = (hasGallery && - generateInfoGalleryLinks(artist, isGallery, { - link, language, - linkKeyGallery: 'artistGallery', - linkKeyInfo: 'artist' - })) +function generateNavForArtist( + artist, + isGallery, + hasGallery, + { generateInfoGalleryLinks, link, language, wikiData } +) { + const { wikiInfo } = wikiData; + + const infoGalleryLinks = + hasGallery && + generateInfoGalleryLinks(artist, isGallery, { + link, + language, + linkKeyGallery: "artistGallery", + linkKeyInfo: "artist", + }); - return { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - wikiInfo.enableListings && - { - path: ['localized.listingIndex'], - title: language.$('listingIndex.title') - }, - { - html: language.$('artistPage.nav.artist', { - artist: link.artist(artist, {class: 'current'}) - }) - }, - hasGallery && - { - divider: false, - html: `(${infoGalleryLinks})` - } - ] - }; + return { + linkContainerClasses: ["nav-links-hierarchy"], + links: [ + { toHome: true }, + wikiInfo.enableListings && { + path: ["localized.listingIndex"], + title: language.$("listingIndex.title"), + }, + { + html: language.$("artistPage.nav.artist", { + artist: link.artist(artist, { class: "current" }), + }), + }, + hasGallery && { + divider: false, + html: `(${infoGalleryLinks})`, + }, + ], + }; } diff --git a/src/page/flash.js b/src/page/flash.js index 21a22b94..4d8b9f11 100644 --- a/src/page/flash.js +++ b/src/page/flash.js @@ -2,251 +2,329 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; -import * as html from '../util/html.js'; +import * as html from "../util/html.js"; -import { - getFlashLink -} from '../util/wiki-data.js'; +import { getFlashLink } from "../util/wiki-data.js"; // Page exports -export function condition({wikiData}) { - return wikiData.wikiInfo.enableFlashesAndGames; +export function condition({ wikiData }) { + return wikiData.wikiInfo.enableFlashesAndGames; } -export function targets({wikiData}) { - return wikiData.flashData; +export function targets({ wikiData }) { + return wikiData.flashData; } -export function write(flash, {wikiData}) { - const page = { - type: 'page', - path: ['flash', flash.directory], - page: ({ - fancifyFlashURL, - generateChronologyLinks, - generateCoverLink, - generatePreviousNextLinks, - getArtistString, - getFlashCover, - getThemeString, - link, - language, - transformInline - }) => ({ - title: language.$('flashPage.title', {flash: flash.name}), - theme: getThemeString(flash.color, [ - `--flash-directory: ${flash.directory}` - ]), - - main: { - content: fixWS` - <h1>${language.$('flashPage.title', {flash: flash.name})}</h1> +export function write(flash, { wikiData }) { + const page = { + type: "page", + path: ["flash", flash.directory], + page: ({ + fancifyFlashURL, + generateChronologyLinks, + generateCoverLink, + generatePreviousNextLinks, + getArtistString, + getFlashCover, + getThemeString, + link, + language, + transformInline, + }) => ({ + title: language.$("flashPage.title", { flash: flash.name }), + theme: getThemeString(flash.color, [ + `--flash-directory: ${flash.directory}`, + ]), + + main: { + content: fixWS` + <h1>${language.$("flashPage.title", { + flash: flash.name, + })}</h1> ${generateCoverLink({ - src: getFlashCover(flash), - alt: language.$('misc.alt.flashArt') + src: getFlashCover(flash), + alt: language.$("misc.alt.flashArt"), })} - <p>${language.$('releaseInfo.released', {date: language.formatDate(flash.date)})}</p> - ${(flash.page || flash.urls?.length) && `<p>${language.$('releaseInfo.playOn', { - links: language.formatDisjunctionList([ + <p>${language.$("releaseInfo.released", { + date: language.formatDate(flash.date), + })}</p> + ${ + (flash.page || flash.urls?.length) && + `<p>${language.$("releaseInfo.playOn", { + links: language.formatDisjunctionList( + [ flash.page && getFlashLink(flash), - ...flash.urls ?? [] - ].map(url => fancifyFlashURL(url, flash))) - })}</p>`} - ${flash.featuredTracks && fixWS` - <p>Tracks featured in <i>${flash.name.replace(/\.$/, '')}</i>:</p> + ...(flash.urls ?? []), + ].map((url) => fancifyFlashURL(url, flash)) + ), + })}</p>` + } + ${ + flash.featuredTracks && + fixWS` + <p>Tracks featured in <i>${flash.name.replace( + /\.$/, + "" + )}</i>:</p> <ul> - ${(flash.featuredTracks - .map(track => language.$('trackList.item.withArtists', { - track: link.track(track), - by: `<span class="by">${ - language.$('trackList.item.withArtists.by', { - artists: getArtistString(track.artistContribs) - }) - }</span>` - })) - .map(row => `<li>${row}</li>`) - .join('\n'))} + ${flash.featuredTracks + .map((track) => + language.$("trackList.item.withArtists", { + track: link.track(track), + by: `<span class="by">${language.$( + "trackList.item.withArtists.by", + { + artists: getArtistString( + track.artistContribs + ), + } + )}</span>`, + }) + ) + .map((row) => `<li>${row}</li>`) + .join("\n")} </ul> - `} - ${flash.contributorContribs.length && fixWS` - <p>${language.$('releaseInfo.contributors')}</p> + ` + } + ${ + flash.contributorContribs.length && + fixWS` + <p>${language.$("releaseInfo.contributors")}</p> <ul> ${flash.contributorContribs - .map(contrib => `<li>${getArtistString([contrib], { + .map( + (contrib) => + `<li>${getArtistString([contrib], { showContrib: true, - showIcons: true - })}</li>`) - .join('\n')} + showIcons: true, + })}</li>` + ) + .join("\n")} </ul> - `} - ` - }, - - sidebarLeft: generateSidebarForFlash(flash, {link, language, wikiData}), - nav: generateNavForFlash(flash, { - generateChronologyLinks, - generatePreviousNextLinks, - link, - language, - wikiData - }) - }) - }; - - return [page]; + ` + } + `, + }, + + sidebarLeft: generateSidebarForFlash(flash, { link, language, wikiData }), + nav: generateNavForFlash(flash, { + generateChronologyLinks, + generatePreviousNextLinks, + link, + language, + wikiData, + }), + }), + }; + + return [page]; } -export function writeTargetless({wikiData}) { - const { flashActData } = wikiData; - - const page = { - type: 'page', - path: ['flashIndex'], - page: ({ - getFlashGridHTML, - getLinkThemeString, - link, - language - }) => ({ - title: language.$('flashIndex.title'), - - main: { - classes: ['flash-index'], - content: fixWS` - <h1>${language.$('flashIndex.title')}</h1> +export function writeTargetless({ wikiData }) { + const { flashActData } = wikiData; + + const page = { + type: "page", + path: ["flashIndex"], + page: ({ getFlashGridHTML, getLinkThemeString, link, language }) => ({ + title: language.$("flashIndex.title"), + + main: { + classes: ["flash-index"], + content: fixWS` + <h1>${language.$("flashIndex.title")}</h1> <div class="long-content"> - <p class="quick-info">${language.$('misc.jumpTo')}</p> + <p class="quick-info">${language.$("misc.jumpTo")}</p> <ul class="quick-info"> - ${flashActData.filter(act => act.jump).map(({ anchor, jump, jumpColor }) => fixWS` - <li><a href="#${anchor}" style="${getLinkThemeString(jumpColor)}">${jump}</a></li> - `).join('\n')} + ${flashActData + .filter((act) => act.jump) + .map( + ({ anchor, jump, jumpColor }) => fixWS` + <li><a href="#${anchor}" style="${getLinkThemeString( + jumpColor + )}">${jump}</a></li> + ` + ) + .join("\n")} </ul> </div> - ${flashActData.map((act, i) => fixWS` - <h2 id="${act.anchor}" style="${getLinkThemeString(act.color)}">${link.flash(act.flashes[0], {text: act.name})}</h2> + ${flashActData + .map( + (act, i) => fixWS` + <h2 id="${act.anchor}" style="${getLinkThemeString( + act.color + )}">${link.flash(act.flashes[0], { + text: act.name, + })}</h2> <div class="grid-listing"> ${getFlashGridHTML({ - entries: act.flashes.map(flash => ({item: flash})), - lazy: i === 0 ? 4 : true + entries: act.flashes.map((flash) => ({ + item: flash, + })), + lazy: i === 0 ? 4 : true, })} </div> - `).join('\n')} - ` - }, + ` + ) + .join("\n")} + `, + }, - nav: {simple: true} - }) - }; + nav: { simple: true }, + }), + }; - return [page]; + return [page]; } // Utility functions -function generateNavForFlash(flash, { +function generateNavForFlash( + flash, + { generateChronologyLinks, generatePreviousNextLinks, link, language, - wikiData -}) { - const { flashData, wikiInfo } = wikiData; - - const previousNextLinks = generatePreviousNextLinks(flash, { - data: flashData, - linkKey: 'flash' - }); - - return { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - { - path: ['localized.flashIndex'], - title: language.$('flashIndex.title') - }, - { - html: language.$('flashPage.nav.flash', { - flash: link.flash(flash, {class: 'current'}) - }) - }, - ], - - bottomRowContent: previousNextLinks && `(${previousNextLinks})`, + wikiData, + } +) { + const { flashData, wikiInfo } = wikiData; - content: fixWS` + const previousNextLinks = generatePreviousNextLinks(flash, { + data: flashData, + linkKey: "flash", + }); + + return { + linkContainerClasses: ["nav-links-hierarchy"], + links: [ + { toHome: true }, + { + path: ["localized.flashIndex"], + title: language.$("flashIndex.title"), + }, + { + html: language.$("flashPage.nav.flash", { + flash: link.flash(flash, { class: "current" }), + }), + }, + ], + + bottomRowContent: previousNextLinks && `(${previousNextLinks})`, + + content: fixWS` <div> ${generateChronologyLinks(flash, { - headingString: 'misc.chronology.heading.flash', - contribKey: 'contributorContribs', - getThings: artist => artist.flashesAsContributor + headingString: "misc.chronology.heading.flash", + contribKey: "contributorContribs", + getThings: (artist) => artist.flashesAsContributor, })} </div> - ` - }; + `, + }; } -function generateSidebarForFlash(flash, {link, language, wikiData}) { - // all hard-coded, sorry :( - // this doesnt have a super portable implementation/design...yet!! - - const { flashActData } = wikiData; - - const act6 = flashActData.findIndex(act => act.name.startsWith('Act 6')); - const postCanon = flashActData.findIndex(act => act.name.includes('Post Canon')); - const outsideCanon = postCanon + flashActData.slice(postCanon).findIndex(act => !act.name.includes('Post Canon')); - const actIndex = flashActData.indexOf(flash.act); - const side = ( - (actIndex < 0) ? 0 : - (actIndex < act6) ? 1 : - (actIndex <= outsideCanon) ? 2 : - 3 - ); - const currentAct = flash && flash.act; - - return { - content: fixWS` - <h1>${link.flashIndex('', {text: language.$('flashIndex.title')})}</h1> +function generateSidebarForFlash(flash, { link, language, wikiData }) { + // all hard-coded, sorry :( + // this doesnt have a super portable implementation/design...yet!! + + const { flashActData } = wikiData; + + const act6 = flashActData.findIndex((act) => act.name.startsWith("Act 6")); + const postCanon = flashActData.findIndex((act) => + act.name.includes("Post Canon") + ); + const outsideCanon = + postCanon + + flashActData + .slice(postCanon) + .findIndex((act) => !act.name.includes("Post Canon")); + const actIndex = flashActData.indexOf(flash.act); + const side = + actIndex < 0 ? 0 : actIndex < act6 ? 1 : actIndex <= outsideCanon ? 2 : 3; + const currentAct = flash && flash.act; + + return { + content: fixWS` + <h1>${link.flashIndex("", { + text: language.$("flashIndex.title"), + })}</h1> <dl> - ${flashActData.filter(act => - act.name.startsWith('Act 1') || - act.name.startsWith('Act 6 Act 1') || - act.name.startsWith('Hiveswap') || - // Sorry not sorry -Yiffy - (({index = flashActData.indexOf(act)} = {}) => ( - index < act6 ? side === 1 : - index < outsideCanon ? side === 2 : - true - ))() - ).flatMap(act => [ - act.name.startsWith('Act 1') && html.tag('dt', - {class: ['side', side === 1 && 'current']}, - link.flash(act.flashes[0], {color: '#4ac925', text: `Side 1 (Acts 1-5)`})) - || act.name.startsWith('Act 6 Act 1') && html.tag('dt', - {class: ['side', side === 2 && 'current']}, - link.flash(act.flashes[0], {color: '#1076a2', text: `Side 2 (Acts 6-7)`})) - || act.name.startsWith('Hiveswap Act 1') && html.tag('dt', - {class: ['side', side === 3 && 'current']}, - link.flash(act.flashes[0], {color: '#008282', text: `Outside Canon (Misc. Games)`})), - (({index = flashActData.indexOf(act)} = {}) => ( - index < act6 ? side === 1 : - index < outsideCanon ? side === 2 : - true - ))() && html.tag('dt', - {class: act === currentAct && 'current'}, - link.flash(act.flashes[0], {text: act.name})), - act === currentAct && fixWS` + ${flashActData + .filter( + (act) => + act.name.startsWith("Act 1") || + act.name.startsWith("Act 6 Act 1") || + act.name.startsWith("Hiveswap") || + // Sorry not sorry -Yiffy + (({ index = flashActData.indexOf(act) } = {}) => + index < act6 + ? side === 1 + : index < outsideCanon + ? side === 2 + : true)() + ) + .flatMap((act) => [ + (act.name.startsWith("Act 1") && + html.tag( + "dt", + { class: ["side", side === 1 && "current"] }, + link.flash(act.flashes[0], { + color: "#4ac925", + text: `Side 1 (Acts 1-5)`, + }) + )) || + (act.name.startsWith("Act 6 Act 1") && + html.tag( + "dt", + { class: ["side", side === 2 && "current"] }, + link.flash(act.flashes[0], { + color: "#1076a2", + text: `Side 2 (Acts 6-7)`, + }) + )) || + (act.name.startsWith("Hiveswap Act 1") && + html.tag( + "dt", + { class: ["side", side === 3 && "current"] }, + link.flash(act.flashes[0], { + color: "#008282", + text: `Outside Canon (Misc. Games)`, + }) + )), + (({ index = flashActData.indexOf(act) } = {}) => + index < act6 + ? side === 1 + : index < outsideCanon + ? side === 2 + : true)() && + html.tag( + "dt", + { class: act === currentAct && "current" }, + link.flash(act.flashes[0], { text: act.name }) + ), + act === currentAct && + fixWS` <dd><ul> - ${act.flashes.map(f => html.tag('li', - {class: f === flash && 'current'}, - link.flash(f))).join('\n')} + ${act.flashes + .map((f) => + html.tag( + "li", + { class: f === flash && "current" }, + link.flash(f) + ) + ) + .join("\n")} </ul></dd> - ` - ]).filter(Boolean).join('\n')} + `, + ]) + .filter(Boolean) + .join("\n")} </dl> - ` - }; + `, + }; } diff --git a/src/page/group.js b/src/page/group.js index b83244a3..bea9ecc7 100644 --- a/src/page/group.js +++ b/src/page/group.js @@ -2,268 +2,326 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; -import * as html from '../util/html.js'; +import * as html from "../util/html.js"; -import { - getTotalDuration, - sortChronologically, -} from '../util/wiki-data.js'; +import { getTotalDuration, sortChronologically } from "../util/wiki-data.js"; // Page exports -export function targets({wikiData}) { - return wikiData.groupData; +export function targets({ wikiData }) { + return wikiData.groupData; } -export function write(group, {wikiData}) { - const { listingSpec, wikiInfo } = wikiData; +export function write(group, { wikiData }) { + const { listingSpec, wikiInfo } = wikiData; - const { albums } = group; - const tracks = albums.flatMap(album => album.tracks); - const totalDuration = getTotalDuration(tracks); + const { albums } = group; + const tracks = albums.flatMap((album) => album.tracks); + const totalDuration = getTotalDuration(tracks); - const albumLines = group.albums.map(album => ({ - album, - otherGroup: album.groups.find(g => g !== group) - })); + const albumLines = group.albums.map((album) => ({ + album, + otherGroup: album.groups.find((g) => g !== group), + })); - const infoPage = { - type: 'page', - path: ['groupInfo', group.directory], - page: ({ - generateInfoGalleryLinks, - generatePreviousNextLinks, - getLinkThemeString, - getThemeString, - fancifyURL, - link, - language, - transformMultiline - }) => ({ - title: language.$('groupInfoPage.title', {group: group.name}), - theme: getThemeString(group.color), + const infoPage = { + type: "page", + path: ["groupInfo", group.directory], + page: ({ + generateInfoGalleryLinks, + generatePreviousNextLinks, + getLinkThemeString, + getThemeString, + fancifyURL, + link, + language, + transformMultiline, + }) => ({ + title: language.$("groupInfoPage.title", { group: group.name }), + theme: getThemeString(group.color), - main: { - content: fixWS` - <h1>${language.$('groupInfoPage.title', {group: group.name})}</h1> - ${group.urls?.length && `<p>${ - language.$('releaseInfo.visitOn', { - links: language.formatDisjunctionList(group.urls.map(url => fancifyURL(url, {language}))) - }) - }</p>`} + main: { + content: fixWS` + <h1>${language.$("groupInfoPage.title", { + group: group.name, + })}</h1> + ${ + group.urls?.length && + `<p>${language.$("releaseInfo.visitOn", { + links: language.formatDisjunctionList( + group.urls.map((url) => fancifyURL(url, { language })) + ), + })}</p>` + } <blockquote> ${transformMultiline(group.description)} </blockquote> - <h2>${language.$('groupInfoPage.albumList.title')}</h2> - <p>${ - language.$('groupInfoPage.viewAlbumGallery', { - link: link.groupGallery(group, { - text: language.$('groupInfoPage.viewAlbumGallery.link') - }) - }) - }</p> + <h2>${language.$("groupInfoPage.albumList.title")}</h2> + <p>${language.$("groupInfoPage.viewAlbumGallery", { + link: link.groupGallery(group, { + text: language.$("groupInfoPage.viewAlbumGallery.link"), + }), + })}</p> <ul> - ${albumLines.map(({ album, otherGroup }) => { - const item = (album.date - ? language.$('groupInfoPage.albumList.item', { - year: album.date.getFullYear(), - album: link.album(album) + ${albumLines + .map(({ album, otherGroup }) => { + const item = album.date + ? language.$("groupInfoPage.albumList.item", { + year: album.date.getFullYear(), + album: link.album(album), }) - : language.$('groupInfoPage.albumList.item.withoutYear', { - album: link.album(album) - })); - return html.tag('li', (otherGroup - ? language.$('groupInfoPage.albumList.item.withAccent', { - item, - accent: html.tag('span', - {class: 'other-group-accent'}, - language.$('groupInfoPage.albumList.item.otherGroupAccent', { - group: link.groupInfo(otherGroup, {color: false}) - })) - }) - : item)); - }).join('\n')} + : language.$( + "groupInfoPage.albumList.item.withoutYear", + { + album: link.album(album), + } + ); + return html.tag( + "li", + otherGroup + ? language.$( + "groupInfoPage.albumList.item.withAccent", + { + item, + accent: html.tag( + "span", + { class: "other-group-accent" }, + language.$( + "groupInfoPage.albumList.item.otherGroupAccent", + { + group: link.groupInfo(otherGroup, { + color: false, + }), + } + ) + ), + } + ) + : item + ); + }) + .join("\n")} </ul> - ` - }, + `, + }, - sidebarLeft: generateGroupSidebar(group, false, { - getLinkThemeString, - link, - language, - wikiData - }), + sidebarLeft: generateGroupSidebar(group, false, { + getLinkThemeString, + link, + language, + wikiData, + }), - nav: generateGroupNav(group, false, { - generateInfoGalleryLinks, - generatePreviousNextLinks, - link, - language, - wikiData - }) - }) - }; + nav: generateGroupNav(group, false, { + generateInfoGalleryLinks, + generatePreviousNextLinks, + link, + language, + wikiData, + }), + }), + }; - const galleryPage = { - type: 'page', - path: ['groupGallery', group.directory], - page: ({ - generateInfoGalleryLinks, - generatePreviousNextLinks, - getAlbumGridHTML, - getLinkThemeString, - getThemeString, - link, - language - }) => ({ - title: language.$('groupGalleryPage.title', {group: group.name}), - theme: getThemeString(group.color), + const galleryPage = { + type: "page", + path: ["groupGallery", group.directory], + page: ({ + generateInfoGalleryLinks, + generatePreviousNextLinks, + getAlbumGridHTML, + getLinkThemeString, + getThemeString, + link, + language, + }) => ({ + title: language.$("groupGalleryPage.title", { group: group.name }), + theme: getThemeString(group.color), - main: { - classes: ['top-index'], - content: fixWS` - <h1>${language.$('groupGalleryPage.title', {group: group.name})}</h1> - <p class="quick-info">${ - language.$('groupGalleryPage.infoLine', { - tracks: `<b>${language.countTracks(tracks.length, {unit: true})}</b>`, - albums: `<b>${language.countAlbums(albums.length, {unit: true})}</b>`, - time: `<b>${language.formatDuration(totalDuration, {unit: true})}</b>` - }) - }</p> - ${wikiInfo.enableGroupUI && wikiInfo.enableListings && html.tag('p', - {class: 'quick-info'}, - language.$('groupGalleryPage.anotherGroupLine', { - link: link.listing(listingSpec.find(l => l.directory === 'groups/by-category'), { - text: language.$('groupGalleryPage.anotherGroupLine.link') - }) + main: { + classes: ["top-index"], + content: fixWS` + <h1>${language.$("groupGalleryPage.title", { + group: group.name, + })}</h1> + <p class="quick-info">${language.$( + "groupGalleryPage.infoLine", + { + tracks: `<b>${language.countTracks(tracks.length, { + unit: true, + })}</b>`, + albums: `<b>${language.countAlbums(albums.length, { + unit: true, + })}</b>`, + time: `<b>${language.formatDuration(totalDuration, { + unit: true, + })}</b>`, + } + )}</p> + ${ + wikiInfo.enableGroupUI && + wikiInfo.enableListings && + html.tag( + "p", + { class: "quick-info" }, + language.$("groupGalleryPage.anotherGroupLine", { + link: link.listing( + listingSpec.find( + (l) => l.directory === "groups/by-category" + ), + { + text: language.$( + "groupGalleryPage.anotherGroupLine.link" + ), + } + ), }) - )} + ) + } <div class="grid-listing"> ${getAlbumGridHTML({ - entries: sortChronologically(group.albums.map(album => ({ - item: album, - directory: album.directory, - name: album.name, - date: album.date, - }))).reverse(), - details: true + entries: sortChronologically( + group.albums.map((album) => ({ + item: album, + directory: album.directory, + name: album.name, + date: album.date, + })) + ).reverse(), + details: true, })} </div> - ` - }, + `, + }, - sidebarLeft: generateGroupSidebar(group, true, { - getLinkThemeString, - link, - language, - wikiData - }), + sidebarLeft: generateGroupSidebar(group, true, { + getLinkThemeString, + link, + language, + wikiData, + }), - nav: generateGroupNav(group, true, { - generateInfoGalleryLinks, - generatePreviousNextLinks, - link, - language, - wikiData - }) - }) - }; + nav: generateGroupNav(group, true, { + generateInfoGalleryLinks, + generatePreviousNextLinks, + link, + language, + wikiData, + }), + }), + }; - return [infoPage, galleryPage]; + return [infoPage, galleryPage]; } // Utility functions -function generateGroupSidebar(currentGroup, isGallery, { - getLinkThemeString, - link, - language, - wikiData -}) { - const { groupCategoryData, wikiInfo } = wikiData; +function generateGroupSidebar( + currentGroup, + isGallery, + { getLinkThemeString, link, language, wikiData } +) { + const { groupCategoryData, wikiInfo } = wikiData; - if (!wikiInfo.enableGroupUI) { - return null; - } + if (!wikiInfo.enableGroupUI) { + return null; + } - const linkKey = isGallery ? 'groupGallery' : 'groupInfo'; + const linkKey = isGallery ? "groupGallery" : "groupInfo"; - return { - content: fixWS` - <h1>${language.$('groupSidebar.title')}</h1> - ${groupCategoryData.map(category => - html.tag('details', { + return { + content: fixWS` + <h1>${language.$("groupSidebar.title")}</h1> + ${groupCategoryData + .map((category) => + html.tag( + "details", + { open: category === currentGroup.category, - class: category === currentGroup.category && 'current' - }, [ - html.tag('summary', - {style: getLinkThemeString(category.color)}, - language.$('groupSidebar.groupList.category', { - category: `<span class="group-name">${category.name}</span>` - })), - html.tag('ul', - category.groups.map(group => html.tag('li', - { - class: group === currentGroup && 'current', - style: getLinkThemeString(group.color) - }, - language.$('groupSidebar.groupList.item', { - group: link[linkKey](group) - })))) - ])).join('\n')} + class: category === currentGroup.category && "current", + }, + [ + html.tag( + "summary", + { style: getLinkThemeString(category.color) }, + language.$("groupSidebar.groupList.category", { + category: `<span class="group-name">${category.name}</span>`, + }) + ), + html.tag( + "ul", + category.groups.map((group) => + html.tag( + "li", + { + class: group === currentGroup && "current", + style: getLinkThemeString(group.color), + }, + language.$("groupSidebar.groupList.item", { + group: link[linkKey](group), + }) + ) + ) + ), + ] + ) + ) + .join("\n")} </dl> - ` - }; + `, + }; } -function generateGroupNav(currentGroup, isGallery, { +function generateGroupNav( + currentGroup, + isGallery, + { generateInfoGalleryLinks, generatePreviousNextLinks, link, language, - wikiData -}) { - const { groupData, wikiInfo } = wikiData; + wikiData, + } +) { + const { groupData, wikiInfo } = wikiData; - if (!wikiInfo.enableGroupUI) { - return {simple: true}; - } + if (!wikiInfo.enableGroupUI) { + return { simple: true }; + } - const urlKey = isGallery ? 'localized.groupGallery' : 'localized.groupInfo'; - const linkKey = isGallery ? 'groupGallery' : 'groupInfo'; + const urlKey = isGallery ? "localized.groupGallery" : "localized.groupInfo"; + const linkKey = isGallery ? "groupGallery" : "groupInfo"; - const infoGalleryLinks = generateInfoGalleryLinks(currentGroup, isGallery, { - linkKeyGallery: 'groupGallery', - linkKeyInfo: 'groupInfo' - }); + const infoGalleryLinks = generateInfoGalleryLinks(currentGroup, isGallery, { + linkKeyGallery: "groupGallery", + linkKeyInfo: "groupInfo", + }); - const previousNextLinks = generatePreviousNextLinks(currentGroup, { - data: groupData, - linkKey - }); + const previousNextLinks = generatePreviousNextLinks(currentGroup, { + data: groupData, + linkKey, + }); - return { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - wikiInfo.enableListings && - { - path: ['localized.listingIndex'], - title: language.$('listingIndex.title') - }, - { - html: language.$('groupPage.nav.group', { - group: link[linkKey](currentGroup, {class: 'current'}) - }) - }, - { - divider: false, - html: (previousNextLinks - ? `(${infoGalleryLinks}; ${previousNextLinks})` - : `(${previousNextLinks})`) - } - ] - }; + return { + linkContainerClasses: ["nav-links-hierarchy"], + links: [ + { toHome: true }, + wikiInfo.enableListings && { + path: ["localized.listingIndex"], + title: language.$("listingIndex.title"), + }, + { + html: language.$("groupPage.nav.group", { + group: link[linkKey](currentGroup, { class: "current" }), + }), + }, + { + divider: false, + html: previousNextLinks + ? `(${infoGalleryLinks}; ${previousNextLinks})` + : `(${previousNextLinks})`, + }, + ], + }; } diff --git a/src/page/homepage.js b/src/page/homepage.js index a19df6cf..ebe3a8d3 100644 --- a/src/page/homepage.js +++ b/src/page/homepage.js @@ -2,123 +2,184 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; -import * as html from '../util/html.js'; +import * as html from "../util/html.js"; -import { - getNewAdditions, - getNewReleases -} from '../util/wiki-data.js'; +import { getNewAdditions, getNewReleases } from "../util/wiki-data.js"; // Page exports -export function writeTargetless({wikiData}) { - const { newsData, staticPageData, homepageLayout, wikiInfo } = wikiData; - - const page = { - type: 'page', - path: ['home'], - page: ({ - getAlbumGridHTML, - getLinkThemeString, - link, - language, - to, - transformInline, - transformMultiline - }) => ({ - title: wikiInfo.name, - showWikiNameInTitle: false, - - meta: { - description: wikiInfo.description - }, - - main: { - classes: ['top-index'], - content: fixWS` +export function writeTargetless({ wikiData }) { + const { newsData, staticPageData, homepageLayout, wikiInfo } = wikiData; + + const page = { + type: "page", + path: ["home"], + page: ({ + getAlbumGridHTML, + getLinkThemeString, + link, + language, + to, + transformInline, + transformMultiline, + }) => ({ + title: wikiInfo.name, + showWikiNameInTitle: false, + + meta: { + description: wikiInfo.description, + }, + + main: { + classes: ["top-index"], + content: fixWS` <h1>${wikiInfo.name}</h1> - ${homepageLayout.rows?.map((row, i) => fixWS` - <section class="row" style="${getLinkThemeString(row.color)}"> + ${homepageLayout.rows + ?.map( + (row, i) => fixWS` + <section class="row" style="${getLinkThemeString( + row.color + )}"> <h2>${row.name}</h2> - ${row.type === 'albums' && fixWS` + ${ + row.type === "albums" && + fixWS` <div class="grid-listing"> ${getAlbumGridHTML({ - entries: ( - row.sourceGroupByRef === 'new-releases' ? getNewReleases(row.countAlbumsFromGroup, {wikiData}) : - row.sourceGroupByRef === 'new-additions' ? getNewAdditions(row.countAlbumsFromGroup, {wikiData}) : - ((row.sourceGroup?.albums ?? []) - .slice() - .reverse() - .filter(album => album.isListedOnHomepage) - .slice(0, row.countAlbumsFromGroup) - .map(album => ({item: album}))) - ).concat(row.sourceAlbums.map(album => ({item: album}))), - lazy: i > 0 + entries: (row.sourceGroupByRef === + "new-releases" + ? getNewReleases( + row.countAlbumsFromGroup, + { wikiData } + ) + : row.sourceGroupByRef === + "new-additions" + ? getNewAdditions( + row.countAlbumsFromGroup, + { wikiData } + ) + : (row.sourceGroup?.albums ?? []) + .slice() + .reverse() + .filter( + (album) => + album.isListedOnHomepage + ) + .slice(0, row.countAlbumsFromGroup) + .map((album) => ({ item: album })) + ).concat( + row.sourceAlbums.map((album) => ({ + item: album, + })) + ), + lazy: i > 0, })} - ${row.actionLinks?.length && fixWS` + ${ + row.actionLinks?.length && + fixWS` <div class="grid-actions"> - ${row.actionLinks.map(action => transformInline(action) - .replace('<a', '<a class="box grid-item"')).join('\n')} + ${row.actionLinks + .map((action) => + transformInline(action).replace( + "<a", + '<a class="box grid-item"' + ) + ) + .join("\n")} </div> - `} + ` + } </div> - `} + ` + } </section> - `).join('\n')} - ` - }, - - sidebarLeft: homepageLayout.sidebarContent && { - wide: true, - collapse: false, - // This is a pretty filthy hack! 8ut otherwise, the [[news]] part - // gets treated like it's a reference to the track named "news", - // which o8viously isn't what we're going for. Gotta catch that - // 8efore we pass it to transformMultiline, 'cuz otherwise it'll - // get repl8ced with just the word "news" (or anything else that - // transformMultiline does with references it can't match) -- and - // we can't match that for replacing it with the news column! - // - // And no, I will not make [[news]] into part of transformMultiline - // (even though that would 8e hilarious). - content: (transformMultiline(homepageLayout.sidebarContent.replace('[[news]]', '__GENERATE_NEWS__')) - .replace('<p>__GENERATE_NEWS__</p>', wikiInfo.enableNews ? fixWS` - <h1>${language.$('homepage.news.title')}</h1> - ${newsData.slice(0, 3).map((entry, i) => html.tag('article', - {class: ['news-entry', i === 0 && 'first-news-entry']}, - fixWS` - <h2><time>${language.formatDate(entry.date)}</time> ${link.newsEntry(entry)}</h2> + ` + ) + .join("\n")} + `, + }, + + sidebarLeft: homepageLayout.sidebarContent && { + wide: true, + collapse: false, + // This is a pretty filthy hack! 8ut otherwise, the [[news]] part + // gets treated like it's a reference to the track named "news", + // which o8viously isn't what we're going for. Gotta catch that + // 8efore we pass it to transformMultiline, 'cuz otherwise it'll + // get repl8ced with just the word "news" (or anything else that + // transformMultiline does with references it can't match) -- and + // we can't match that for replacing it with the news column! + // + // And no, I will not make [[news]] into part of transformMultiline + // (even though that would 8e hilarious). + content: transformMultiline( + homepageLayout.sidebarContent.replace("[[news]]", "__GENERATE_NEWS__") + ).replace( + "<p>__GENERATE_NEWS__</p>", + wikiInfo.enableNews + ? fixWS` + <h1>${language.$("homepage.news.title")}</h1> + ${newsData + .slice(0, 3) + .map((entry, i) => + html.tag( + "article", + { + class: [ + "news-entry", + i === 0 && "first-news-entry", + ], + }, + fixWS` + <h2><time>${language.formatDate( + entry.date + )}</time> ${link.newsEntry(entry)}</h2> ${transformMultiline(entry.contentShort)} - ${entry.contentShort !== entry.content && link.newsEntry(entry, { - text: language.$('homepage.news.entry.viewRest') - })} - `)).join('\n')} - ` : `<p><i>News requested in content description but this feature isn't enabled</i></p>`)) - }, - - nav: { - linkContainerClasses: ['nav-links-index'], - links: [ - link.home('', {text: wikiInfo.nameShort, class: 'current', to}), - - wikiInfo.enableListings && - link.listingIndex('', {text: language.$('listingIndex.title'), to}), - - wikiInfo.enableNews && - link.newsIndex('', {text: language.$('newsIndex.title'), to}), - - wikiInfo.enableFlashesAndGames && - link.flashIndex('', {text: language.$('flashIndex.title'), to}), - - ...(staticPageData - .filter(page => page.showInNavigationBar) - .map(page => link.staticPage(page, {text: page.nameShort}))), - ].filter(Boolean).map(html => ({html})), - } - }) - }; - - return [page]; + ${ + entry.contentShort !== entry.content && + link.newsEntry(entry, { + text: language.$( + "homepage.news.entry.viewRest" + ), + }) + } + ` + ) + ) + .join("\n")} + ` + : `<p><i>News requested in content description but this feature isn't enabled</i></p>` + ), + }, + + nav: { + linkContainerClasses: ["nav-links-index"], + links: [ + link.home("", { text: wikiInfo.nameShort, class: "current", to }), + + wikiInfo.enableListings && + link.listingIndex("", { + text: language.$("listingIndex.title"), + to, + }), + + wikiInfo.enableNews && + link.newsIndex("", { text: language.$("newsIndex.title"), to }), + + wikiInfo.enableFlashesAndGames && + link.flashIndex("", { text: language.$("flashIndex.title"), to }), + + ...staticPageData + .filter((page) => page.showInNavigationBar) + .map((page) => link.staticPage(page, { text: page.nameShort })), + ] + .filter(Boolean) + .map((html) => ({ html })), + }, + }), + }; + + return [page]; } diff --git a/src/page/index.js b/src/page/index.js index f580cbea..50fbd7a4 100644 --- a/src/page/index.js +++ b/src/page/index.js @@ -39,15 +39,15 @@ // These functions should be referenced only from adjacent modules, as they // pertain only to site page generation. -export * as album from './album.js'; -export * as albumCommentary from './album-commentary.js'; -export * as artist from './artist.js'; -export * as artistAlias from './artist-alias.js'; -export * as flash from './flash.js'; -export * as group from './group.js'; -export * as homepage from './homepage.js'; -export * as listing from './listing.js'; -export * as news from './news.js'; -export * as static from './static.js'; -export * as tag from './tag.js'; -export * as track from './track.js'; +export * as album from "./album.js"; +export * as albumCommentary from "./album-commentary.js"; +export * as artist from "./artist.js"; +export * as artistAlias from "./artist-alias.js"; +export * as flash from "./flash.js"; +export * as group from "./group.js"; +export * as homepage from "./homepage.js"; +export * as listing from "./listing.js"; +export * as news from "./news.js"; +export * as static from "./static.js"; +export * as tag from "./tag.js"; +export * as track from "./track.js"; diff --git a/src/page/listing.js b/src/page/listing.js index 447a0c8f..886c8a9d 100644 --- a/src/page/listing.js +++ b/src/page/listing.js @@ -10,193 +10,218 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; -import * as html from '../util/html.js'; +import * as html from "../util/html.js"; -import { - getTotalDuration -} from '../util/wiki-data.js'; +import { getTotalDuration } from "../util/wiki-data.js"; // Page exports -export function condition({wikiData}) { - return wikiData.wikiInfo.enableListings; +export function condition({ wikiData }) { + return wikiData.wikiInfo.enableListings; } -export function targets({wikiData}) { - return wikiData.listingSpec; +export function targets({ wikiData }) { + return wikiData.listingSpec; } -export function write(listing, {wikiData}) { - if (listing.condition && !listing.condition({wikiData})) { - return null; - } +export function write(listing, { wikiData }) { + if (listing.condition && !listing.condition({ wikiData })) { + return null; + } - const { wikiInfo } = wikiData; + const { wikiInfo } = wikiData; - const data = (listing.data - ? listing.data({wikiData}) - : null); + const data = listing.data ? listing.data({ wikiData }) : null; - const page = { - type: 'page', - path: ['listing', listing.directory], - page: opts => { - const { getLinkThemeString, link, language } = opts; - const titleKey = `listingPage.${listing.stringsKey}.title`; + const page = { + type: "page", + path: ["listing", listing.directory], + page: (opts) => { + const { getLinkThemeString, link, language } = opts; + const titleKey = `listingPage.${listing.stringsKey}.title`; - return { - title: language.$(titleKey), + return { + title: language.$(titleKey), - main: { - content: fixWS` + main: { + content: fixWS` <h1>${language.$(titleKey)}</h1> - ${listing.html && (listing.data + ${ + listing.html && + (listing.data ? listing.html(data, opts) - : listing.html(opts))} - ${listing.row && fixWS` + : listing.html(opts)) + } + ${ + listing.row && + fixWS` <ul> - ${(data - .map(item => listing.row(item, opts)) - .map(row => `<li>${row}</li>`) - .join('\n'))} + ${data + .map((item) => listing.row(item, opts)) + .map((row) => `<li>${row}</li>`) + .join("\n")} </ul> - `} - ` - }, - - sidebarLeft: { - content: generateSidebarForListings(listing, { - getLinkThemeString, - link, - language, - wikiData - }) - }, - - nav: { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - { - path: ['localized.listingIndex'], - title: language.$('listingIndex.title') - }, - {toCurrentPage: true} - ] - } - }; - } - }; - - return [page]; -} - -export function writeTargetless({wikiData}) { - const { albumData, trackData, wikiInfo } = wikiData; + ` + } + `, + }, - const totalDuration = getTotalDuration(trackData); - - const page = { - type: 'page', - path: ['listingIndex'], - page: ({ + sidebarLeft: { + content: generateSidebarForListings(listing, { getLinkThemeString, + link, language, - link - }) => ({ - title: language.$('listingIndex.title'), - - main: { - content: fixWS` - <h1>${language.$('listingIndex.title')}</h1> - <p>${language.$('listingIndex.infoLine', { - wiki: wikiInfo.name, - tracks: `<b>${language.countTracks(trackData.length, {unit: true})}</b>`, - albums: `<b>${language.countAlbums(albumData.length, {unit: true})}</b>`, - duration: `<b>${language.formatDuration(totalDuration, {approximate: true, unit: true})}</b>` - })}</p> - <hr> - <p>${language.$('listingIndex.exploreList')}</p> - ${generateLinkIndexForListings(null, false, {link, language, wikiData})} - ` - }, - - sidebarLeft: { - content: generateSidebarForListings(null, { - getLinkThemeString, - link, - language, - wikiData - }) + wikiData, + }), + }, + + nav: { + linkContainerClasses: ["nav-links-hierarchy"], + links: [ + { toHome: true }, + { + path: ["localized.listingIndex"], + title: language.$("listingIndex.title"), }, + { toCurrentPage: true }, + ], + }, + }; + }, + }; + + return [page]; +} - nav: {simple: true} - }) - }; - - return [page]; -}; +export function writeTargetless({ wikiData }) { + const { albumData, trackData, wikiInfo } = wikiData; + + const totalDuration = getTotalDuration(trackData); + + const page = { + type: "page", + path: ["listingIndex"], + page: ({ getLinkThemeString, language, link }) => ({ + title: language.$("listingIndex.title"), + + main: { + content: fixWS` + <h1>${language.$("listingIndex.title")}</h1> + <p>${language.$("listingIndex.infoLine", { + wiki: wikiInfo.name, + tracks: `<b>${language.countTracks(trackData.length, { + unit: true, + })}</b>`, + albums: `<b>${language.countAlbums(albumData.length, { + unit: true, + })}</b>`, + duration: `<b>${language.formatDuration(totalDuration, { + approximate: true, + unit: true, + })}</b>`, + })}</p> + <hr> + <p>${language.$("listingIndex.exploreList")}</p> + ${generateLinkIndexForListings(null, false, { + link, + language, + wikiData, + })} + `, + }, + + sidebarLeft: { + content: generateSidebarForListings(null, { + getLinkThemeString, + link, + language, + wikiData, + }), + }, + + nav: { simple: true }, + }), + }; + + return [page]; +} // Utility functions -function generateSidebarForListings(currentListing, { - getLinkThemeString, - link, - language, - wikiData -}) { - return fixWS` - <h1>${link.listingIndex('', {text: language.$('listingIndex.title')})}</h1> +function generateSidebarForListings( + currentListing, + { getLinkThemeString, link, language, wikiData } +) { + return fixWS` + <h1>${link.listingIndex("", { + text: language.$("listingIndex.title"), + })}</h1> ${generateLinkIndexForListings(currentListing, true, { - getLinkThemeString, - link, - language, - wikiData + getLinkThemeString, + link, + language, + wikiData, })} `; } -function generateLinkIndexForListings(currentListing, forSidebar, { - getLinkThemeString, - link, - language, - wikiData -}) { - const { listingTargetSpec, wikiInfo } = wikiData; - - const filteredByCondition = listingTargetSpec - .map(({ listings, ...rest }) => ({ - ...rest, - listings: listings.filter(({ condition: c }) => !c || c({wikiData})) - })) - .filter(({ listings }) => listings.length > 0); - - const genUL = listings => html.tag('ul', - listings.map(listing => html.tag('li', - {class: [listing === currentListing && 'current']}, - link.listing(listing, {text: language.$(`listingPage.${listing.stringsKey}.title.short`)}) - ))); - - if (forSidebar) { - return filteredByCondition.map(({ title, listings }) => - html.tag('details', { - open: !forSidebar || listings.includes(currentListing), - class: listings.includes(currentListing) && 'current' - }, [ - html.tag('summary', - {style: getLinkThemeString(wikiInfo.color)}, - html.tag('span', - {class: 'group-name'}, - title({language}))), - genUL(listings) - ])).join('\n'); - } else { - return html.tag('dl', - filteredByCondition.flatMap(({ title, listings }) => [ - html.tag('dt', title({language})), - html.tag('dd', genUL(listings)) - ])); - } +function generateLinkIndexForListings( + currentListing, + forSidebar, + { getLinkThemeString, link, language, wikiData } +) { + const { listingTargetSpec, wikiInfo } = wikiData; + + const filteredByCondition = listingTargetSpec + .map(({ listings, ...rest }) => ({ + ...rest, + listings: listings.filter(({ condition: c }) => !c || c({ wikiData })), + })) + .filter(({ listings }) => listings.length > 0); + + const genUL = (listings) => + html.tag( + "ul", + listings.map((listing) => + html.tag( + "li", + { class: [listing === currentListing && "current"] }, + link.listing(listing, { + text: language.$(`listingPage.${listing.stringsKey}.title.short`), + }) + ) + ) + ); + + if (forSidebar) { + return filteredByCondition + .map(({ title, listings }) => + html.tag( + "details", + { + open: !forSidebar || listings.includes(currentListing), + class: listings.includes(currentListing) && "current", + }, + [ + html.tag( + "summary", + { style: getLinkThemeString(wikiInfo.color) }, + html.tag("span", { class: "group-name" }, title({ language })) + ), + genUL(listings), + ] + ) + ) + .join("\n"); + } else { + return html.tag( + "dl", + filteredByCondition.flatMap(({ title, listings }) => [ + html.tag("dt", title({ language })), + html.tag("dd", genUL(listings)), + ]) + ); + } } diff --git a/src/page/news.js b/src/page/news.js index 9336506f..2fc5d7b0 100644 --- a/src/page/news.js +++ b/src/page/news.js @@ -2,126 +2,135 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; // Page exports -export function condition({wikiData}) { - return wikiData.wikiInfo.enableNews; +export function condition({ wikiData }) { + return wikiData.wikiInfo.enableNews; } -export function targets({wikiData}) { - return wikiData.newsData; +export function targets({ wikiData }) { + return wikiData.newsData; } -export function write(entry, {wikiData}) { - const page = { - type: 'page', - path: ['newsEntry', entry.directory], - page: ({ - generatePreviousNextLinks, - link, - language, - transformMultiline, - }) => ({ - title: language.$('newsEntryPage.title', {entry: entry.name}), - - main: { - content: fixWS` +export function write(entry, { wikiData }) { + const page = { + type: "page", + path: ["newsEntry", entry.directory], + page: ({ + generatePreviousNextLinks, + link, + language, + transformMultiline, + }) => ({ + title: language.$("newsEntryPage.title", { entry: entry.name }), + + main: { + content: fixWS` <div class="long-content"> - <h1>${language.$('newsEntryPage.title', {entry: entry.name})}</h1> - <p>${language.$('newsEntryPage.published', {date: language.formatDate(entry.date)})}</p> + <h1>${language.$("newsEntryPage.title", { + entry: entry.name, + })}</h1> + <p>${language.$("newsEntryPage.published", { + date: language.formatDate(entry.date), + })}</p> ${transformMultiline(entry.content)} </div> - ` - }, - - nav: generateNewsEntryNav(entry, { - generatePreviousNextLinks, - link, - language, - wikiData - }) - }) - }; - - return [page]; + `, + }, + + nav: generateNewsEntryNav(entry, { + generatePreviousNextLinks, + link, + language, + wikiData, + }), + }), + }; + + return [page]; } -export function writeTargetless({wikiData}) { - const { newsData } = wikiData; - - const page = { - type: 'page', - path: ['newsIndex'], - page: ({ - link, - language, - transformMultiline - }) => ({ - title: language.$('newsIndex.title'), - - main: { - content: fixWS` +export function writeTargetless({ wikiData }) { + const { newsData } = wikiData; + + const page = { + type: "page", + path: ["newsIndex"], + page: ({ link, language, transformMultiline }) => ({ + title: language.$("newsIndex.title"), + + main: { + content: fixWS` <div class="long-content news-index"> - <h1>${language.$('newsIndex.title')}</h1> - ${newsData.map(entry => fixWS` + <h1>${language.$("newsIndex.title")}</h1> + ${newsData + .map( + (entry) => fixWS` <article id="${entry.directory}"> - <h2><time>${language.formatDate(entry.date)}</time> ${link.newsEntry(entry)}</h2> + <h2><time>${language.formatDate( + entry.date + )}</time> ${link.newsEntry(entry)}</h2> ${transformMultiline(entry.contentShort)} - ${entry.contentShort !== entry.content && `<p>${link.newsEntry(entry, { - text: language.$('newsIndex.entry.viewRest') - })}</p>`} + ${ + entry.contentShort !== entry.content && + `<p>${link.newsEntry(entry, { + text: language.$( + "newsIndex.entry.viewRest" + ), + })}</p>` + } </article> - `).join('\n')} + ` + ) + .join("\n")} </div> - ` - }, + `, + }, - nav: {simple: true} - }) - }; + nav: { simple: true }, + }), + }; - return [page]; + return [page]; } // Utility functions -function generateNewsEntryNav(entry, { - generatePreviousNextLinks, +function generateNewsEntryNav( + entry, + { generatePreviousNextLinks, link, language, wikiData } +) { + const { wikiInfo, newsData } = wikiData; + + // The newsData list is sorted reverse chronologically (newest ones first), + // so the way we find next/previous entries is flipped from normal. + const previousNextLinks = generatePreviousNextLinks(entry, { link, language, - wikiData -}) { - const { wikiInfo, newsData } = wikiData; - - // The newsData list is sorted reverse chronologically (newest ones first), - // so the way we find next/previous entries is flipped from normal. - const previousNextLinks = generatePreviousNextLinks(entry, { - link, language, - data: newsData.slice().reverse(), - linkKey: 'newsEntry' - }); - - return { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - { - path: ['localized.newsIndex'], - title: language.$('newsEntryPage.nav.news') - }, - { - html: language.$('newsEntryPage.nav.entry', { - date: language.formatDate(entry.date), - entry: link.newsEntry(entry, {class: 'current'}) - }) - }, - previousNextLinks && - { - divider: false, - html: `(${previousNextLinks})` - } - ] - }; + data: newsData.slice().reverse(), + linkKey: "newsEntry", + }); + + return { + linkContainerClasses: ["nav-links-hierarchy"], + links: [ + { toHome: true }, + { + path: ["localized.newsIndex"], + title: language.$("newsEntryPage.nav.news"), + }, + { + html: language.$("newsEntryPage.nav.entry", { + date: language.formatDate(entry.date), + entry: link.newsEntry(entry, { class: "current" }), + }), + }, + previousNextLinks && { + divider: false, + html: `(${previousNextLinks})`, + }, + ], + }; } diff --git a/src/page/static.js b/src/page/static.js index e9b6a047..39acd64e 100644 --- a/src/page/static.js +++ b/src/page/static.js @@ -4,37 +4,34 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; // Page exports -export function targets({wikiData}) { - return wikiData.staticPageData; +export function targets({ wikiData }) { + return wikiData.staticPageData; } -export function write(staticPage, {wikiData}) { - const page = { - type: 'page', - path: ['staticPage', staticPage.directory], - page: ({ - language, - transformMultiline - }) => ({ - title: staticPage.name, - stylesheet: staticPage.stylesheet, - - main: { - content: fixWS` +export function write(staticPage, { wikiData }) { + const page = { + type: "page", + path: ["staticPage", staticPage.directory], + page: ({ language, transformMultiline }) => ({ + title: staticPage.name, + stylesheet: staticPage.stylesheet, + + main: { + content: fixWS` <div class="long-content"> <h1>${staticPage.name}</h1> ${transformMultiline(staticPage.content)} </div> - ` - }, + `, + }, - nav: {simple: true} - }) - }; + nav: { simple: true }, + }), + }; - return [page]; + return [page]; } diff --git a/src/page/tag.js b/src/page/tag.js index 471439da..98b552b3 100644 --- a/src/page/tag.js +++ b/src/page/tag.js @@ -2,110 +2,111 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; // Page exports -export function condition({wikiData}) { - return wikiData.wikiInfo.enableArtTagUI; +export function condition({ wikiData }) { + return wikiData.wikiInfo.enableArtTagUI; } -export function targets({wikiData}) { - return wikiData.artTagData.filter(tag => !tag.isContentWarning); +export function targets({ wikiData }) { + return wikiData.artTagData.filter((tag) => !tag.isContentWarning); } -export function write(tag, {wikiData}) { - const { wikiInfo } = wikiData; - const { taggedInThings: things } = tag; +export function write(tag, { wikiData }) { + const { wikiInfo } = wikiData; + const { taggedInThings: things } = tag; - // Display things featuring this art tag in reverse chronological order, - // sticking the most recent additions near the top! - const thingsReversed = things.slice().reverse(); + // Display things featuring this art tag in reverse chronological order, + // sticking the most recent additions near the top! + const thingsReversed = things.slice().reverse(); - const entries = thingsReversed.map(item => ({item})); + const entries = thingsReversed.map((item) => ({ item })); - const page = { - type: 'page', - path: ['tag', tag.directory], - page: ({ - generatePreviousNextLinks, - getAlbumCover, - getGridHTML, - getThemeString, - getTrackCover, - link, - language, - to - }) => ({ - title: language.$('tagPage.title', {tag: tag.name}), - theme: getThemeString(tag.color), + const page = { + type: "page", + path: ["tag", tag.directory], + page: ({ + generatePreviousNextLinks, + getAlbumCover, + getGridHTML, + getThemeString, + getTrackCover, + link, + language, + to, + }) => ({ + title: language.$("tagPage.title", { tag: tag.name }), + theme: getThemeString(tag.color), - main: { - classes: ['top-index'], - content: fixWS` - <h1>${language.$('tagPage.title', {tag: tag.name})}</h1> - <p class="quick-info">${language.$('tagPage.infoLine', { - coverArts: language.countCoverArts(things.length, {unit: true}) + main: { + classes: ["top-index"], + content: fixWS` + <h1>${language.$("tagPage.title", { tag: tag.name })}</h1> + <p class="quick-info">${language.$("tagPage.infoLine", { + coverArts: language.countCoverArts(things.length, { + unit: true, + }), })}</p> <div class="grid-listing"> ${getGridHTML({ - entries, - srcFn: thing => (thing.album - ? getTrackCover(thing) - : getAlbumCover(thing)), - linkFn: (thing, opts) => (thing.album - ? link.track(thing, opts) - : link.album(thing, opts)) + entries, + srcFn: (thing) => + thing.album + ? getTrackCover(thing) + : getAlbumCover(thing), + linkFn: (thing, opts) => + thing.album + ? link.track(thing, opts) + : link.album(thing, opts), })} </div> - ` - }, + `, + }, - nav: generateTagNav(tag, { - generatePreviousNextLinks, - link, - language, - wikiData - }) - }) - }; + nav: generateTagNav(tag, { + generatePreviousNextLinks, + link, + language, + wikiData, + }), + }), + }; - return [page]; + return [page]; } // Utility functions -function generateTagNav(tag, { - generatePreviousNextLinks, - link, - language, - wikiData -}) { - const previousNextLinks = generatePreviousNextLinks(tag, { - data: wikiData.artTagData.filter(tag => !tag.isContentWarning), - linkKey: 'tag' - }); +function generateTagNav( + tag, + { generatePreviousNextLinks, link, language, wikiData } +) { + const previousNextLinks = generatePreviousNextLinks(tag, { + data: wikiData.artTagData.filter((tag) => !tag.isContentWarning), + linkKey: "tag", + }); - return { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - wikiData.wikiInfo.enableListings && - { - path: ['localized.listingIndex'], - title: language.$('listingIndex.title') - }, - { - html: language.$('tagPage.nav.tag', { - tag: link.tag(tag, {class: 'current'}) - }) - }, - /* + return { + linkContainerClasses: ["nav-links-hierarchy"], + links: [ + { toHome: true }, + wikiData.wikiInfo.enableListings && { + path: ["localized.listingIndex"], + title: language.$("listingIndex.title"), + }, + { + html: language.$("tagPage.nav.tag", { + tag: link.tag(tag, { class: "current" }), + }), + }, + /* previousNextLinks && { divider: false, html: `(${previousNextLinks})` } */ - ] - }; + ], + }; } diff --git a/src/page/track.js b/src/page/track.js index c4ec6c59..15316e8f 100644 --- a/src/page/track.js +++ b/src/page/track.js @@ -2,186 +2,221 @@ // Imports -import fixWS from 'fix-whitespace'; +import fixWS from "fix-whitespace"; import { - generateAlbumChronologyLinks, - generateAlbumNavLinks, - generateAlbumSecondaryNav, - generateAlbumSidebar -} from './album.js'; + generateAlbumChronologyLinks, + generateAlbumNavLinks, + generateAlbumSecondaryNav, + generateAlbumSidebar, +} from "./album.js"; -import * as html from '../util/html.js'; +import * as html from "../util/html.js"; -import { - bindOpts -} from '../util/sugar.js'; +import { bindOpts } from "../util/sugar.js"; import { - getTrackCover, - getAlbumListTag, - sortChronologically, -} from '../util/wiki-data.js'; + getTrackCover, + getAlbumListTag, + sortChronologically, +} from "../util/wiki-data.js"; // Page exports -export function targets({wikiData}) { - return wikiData.trackData; +export function targets({ wikiData }) { + return wikiData.trackData; } -export function write(track, {wikiData}) { - const { groupData, wikiInfo } = wikiData; - const { album, referencedByTracks, referencedTracks, otherReleases } = track; +export function write(track, { wikiData }) { + const { groupData, wikiInfo } = wikiData; + const { album, referencedByTracks, referencedTracks, otherReleases } = track; - const listTag = getAlbumListTag(album); + const listTag = getAlbumListTag(album); - let flashesThatFeature; - if (wikiInfo.enableFlashesAndGames) { - flashesThatFeature = sortChronologically([track, ...otherReleases] - .flatMap(track => track.featuredInFlashes - .map(flash => ({ - flash, - as: track, - directory: flash.directory, - name: flash.name, - date: flash.date - })))); - } + let flashesThatFeature; + if (wikiInfo.enableFlashesAndGames) { + flashesThatFeature = sortChronologically( + [track, ...otherReleases].flatMap((track) => + track.featuredInFlashes.map((flash) => ({ + flash, + as: track, + directory: flash.directory, + name: flash.name, + date: flash.date, + })) + ) + ); + } - const unbound_getTrackItem = (track, {getArtistString, link, language}) => ( - html.tag('li', language.$('trackList.item.withArtists', { - track: link.track(track), - by: `<span class="by">${language.$('trackList.item.withArtists.by', { - artists: getArtistString(track.artistContribs) - })}</span>` - }))); + const unbound_getTrackItem = (track, { getArtistString, link, language }) => + html.tag( + "li", + language.$("trackList.item.withArtists", { + track: link.track(track), + by: `<span class="by">${language.$("trackList.item.withArtists.by", { + artists: getArtistString(track.artistContribs), + })}</span>`, + }) + ); - const unbound_generateTrackList = (tracks, {getArtistString, link, language}) => html.tag('ul', - tracks.map(track => unbound_getTrackItem(track, {getArtistString, link, language})) + const unbound_generateTrackList = ( + tracks, + { getArtistString, link, language } + ) => + html.tag( + "ul", + tracks.map((track) => + unbound_getTrackItem(track, { getArtistString, link, language }) + ) ); - const hasCommentary = track.commentary || otherReleases.some(t => t.commentary); - const generateCommentary = ({ - link, - language, - transformMultiline - }) => transformMultiline([ + const hasCommentary = + track.commentary || otherReleases.some((t) => t.commentary); + const generateCommentary = ({ link, language, transformMultiline }) => + transformMultiline( + [ track.commentary, - ...otherReleases.map(track => - (track.commentary?.split('\n') - .filter(line => line.replace(/<\/b>/g, '').includes(':</i>')) - .map(line => fixWS` + ...otherReleases.map((track) => + track.commentary + ?.split("\n") + .filter((line) => line.replace(/<\/b>/g, "").includes(":</i>")) + .map( + (line) => fixWS` ${line} - ${language.$('releaseInfo.artistCommentary.seeOriginalRelease', { - original: link.track(track) - })} - `) - .join('\n'))) - ].filter(Boolean).join('\n')); + ${language.$( + "releaseInfo.artistCommentary.seeOriginalRelease", + { + original: link.track(track), + } + )} + ` + ) + .join("\n") + ), + ] + .filter(Boolean) + .join("\n") + ); - const data = { - type: 'data', - path: ['track', track.directory], - data: ({ - serializeContribs, - serializeCover, - serializeGroupsForTrack, - serializeLink - }) => ({ - name: track.name, - directory: track.directory, - dates: { - released: track.date, - originallyReleased: track.originalDate, - coverArtAdded: track.coverArtDate - }, - duration: track.duration, - color: track.color, - cover: serializeCover(track, getTrackCover), - artistsContribs: serializeContribs(track.artistContribs), - contributorContribs: serializeContribs(track.contributorContribs), - coverArtistContribs: serializeContribs(track.coverArtistContribs || []), - album: serializeLink(track.album), - groups: serializeGroupsForTrack(track), - references: track.references.map(serializeLink), - referencedBy: track.referencedBy.map(serializeLink), - alsoReleasedAs: otherReleases.map(track => ({ - track: serializeLink(track), - album: serializeLink(track.album) - })) - }) - }; + const data = { + type: "data", + path: ["track", track.directory], + data: ({ + serializeContribs, + serializeCover, + serializeGroupsForTrack, + serializeLink, + }) => ({ + name: track.name, + directory: track.directory, + dates: { + released: track.date, + originallyReleased: track.originalDate, + coverArtAdded: track.coverArtDate, + }, + duration: track.duration, + color: track.color, + cover: serializeCover(track, getTrackCover), + artistsContribs: serializeContribs(track.artistContribs), + contributorContribs: serializeContribs(track.contributorContribs), + coverArtistContribs: serializeContribs(track.coverArtistContribs || []), + album: serializeLink(track.album), + groups: serializeGroupsForTrack(track), + references: track.references.map(serializeLink), + referencedBy: track.referencedBy.map(serializeLink), + alsoReleasedAs: otherReleases.map((track) => ({ + track: serializeLink(track), + album: serializeLink(track.album), + })), + }), + }; - const getSocialEmbedDescription = ({ - getArtistString: _getArtistString, - language, - }) => { - const hasArtists = (track.artistContribs?.length > 0); - const hasCoverArtists = (track.coverArtistContribs?.length > 0); - const getArtistString = contribs => _getArtistString(contribs, { - // We don't want to put actual HTML tags in social embeds (sadly - // they don't get parsed and displayed, generally speaking), so - // override the link argument so that artist "links" just show - // their names. - link: {artist: artist => artist.name} - }); - if (!hasArtists && !hasCoverArtists) return ''; - return language.formatString( - 'trackPage.socialEmbed.body' + [ - hasArtists && '.withArtists', - hasCoverArtists && '.withCoverArtists', - ].filter(Boolean).join(''), - Object.fromEntries([ - hasArtists && ['artists', getArtistString(track.artistContribs)], - hasCoverArtists && ['coverArtists', getArtistString(track.coverArtistContribs)], - ].filter(Boolean))) - }; + const getSocialEmbedDescription = ({ + getArtistString: _getArtistString, + language, + }) => { + const hasArtists = track.artistContribs?.length > 0; + const hasCoverArtists = track.coverArtistContribs?.length > 0; + const getArtistString = (contribs) => + _getArtistString(contribs, { + // We don't want to put actual HTML tags in social embeds (sadly + // they don't get parsed and displayed, generally speaking), so + // override the link argument so that artist "links" just show + // their names. + link: { artist: (artist) => artist.name }, + }); + if (!hasArtists && !hasCoverArtists) return ""; + return language.formatString( + "trackPage.socialEmbed.body" + + [hasArtists && ".withArtists", hasCoverArtists && ".withCoverArtists"] + .filter(Boolean) + .join(""), + Object.fromEntries( + [ + hasArtists && ["artists", getArtistString(track.artistContribs)], + hasCoverArtists && [ + "coverArtists", + getArtistString(track.coverArtistContribs), + ], + ].filter(Boolean) + ) + ); + }; - const page = { - type: 'page', - path: ['track', track.directory], - page: ({ - absoluteTo, - fancifyURL, - generateChronologyLinks, - generateCoverLink, - generatePreviousNextLinks, - generateTrackListDividedByGroups, - getAlbumStylesheet, - getArtistString, - getLinkThemeString, - getThemeString, - getTrackCover, - link, - language, - transformInline, - transformLyrics, - transformMultiline, - to, - urls, - }) => { - const getTrackItem = bindOpts(unbound_getTrackItem, {getArtistString, link, language}); - const cover = getTrackCover(track); + const page = { + type: "page", + path: ["track", track.directory], + page: ({ + absoluteTo, + fancifyURL, + generateChronologyLinks, + generateCoverLink, + generatePreviousNextLinks, + generateTrackListDividedByGroups, + getAlbumStylesheet, + getArtistString, + getLinkThemeString, + getThemeString, + getTrackCover, + link, + language, + transformInline, + transformLyrics, + transformMultiline, + to, + urls, + }) => { + const getTrackItem = bindOpts(unbound_getTrackItem, { + getArtistString, + link, + language, + }); + const cover = getTrackCover(track); - return { - title: language.$('trackPage.title', {track: track.name}), - stylesheet: getAlbumStylesheet(album, {to}), - theme: getThemeString(track.color, [ - `--album-directory: ${album.directory}`, - `--track-directory: ${track.directory}` - ]), + return { + title: language.$("trackPage.title", { track: track.name }), + stylesheet: getAlbumStylesheet(album, { to }), + theme: getThemeString(track.color, [ + `--album-directory: ${album.directory}`, + `--track-directory: ${track.directory}`, + ]), - socialEmbed: { - heading: language.$('trackPage.socialEmbed.heading', {album: track.album.name}), - headingLink: absoluteTo('localized.album', album.directory), - title: language.$('trackPage.socialEmbed.title', {track: track.name}), - description: getSocialEmbedDescription({getArtistString, language}), - image: '/' + getTrackCover(track, {to: urls.from('shared.root').to}), - color: track.color, - }, + socialEmbed: { + heading: language.$("trackPage.socialEmbed.heading", { + album: track.album.name, + }), + headingLink: absoluteTo("localized.album", album.directory), + title: language.$("trackPage.socialEmbed.title", { + track: track.name, + }), + description: getSocialEmbedDescription({ getArtistString, language }), + image: + "/" + getTrackCover(track, { to: urls.from("shared.root").to }), + color: track.color, + }, - // disabled for now! shifting banner position per height of page is disorienting - /* + // disabled for now! shifting banner position per height of page is disorienting + /* banner: album.bannerArtistContribs.length && { classes: ['dim'], dimensions: album.bannerDimensions, @@ -191,156 +226,239 @@ export function write(track, {wikiData}) { }, */ - main: { - content: fixWS` - ${cover && generateCoverLink({ + main: { + content: fixWS` + ${ + cover && + generateCoverLink({ src: cover, - alt: language.$('misc.alt.trackCover'), - tags: track.artTags - })} - <h1>${language.$('trackPage.title', {track: track.name})}</h1> + alt: language.$("misc.alt.trackCover"), + tags: track.artTags, + }) + } + <h1>${language.$("trackPage.title", { + track: track.name, + })}</h1> <p> ${[ - language.$('releaseInfo.by', { - artists: getArtistString(track.artistContribs, { - showContrib: true, - showIcons: true - }) + language.$("releaseInfo.by", { + artists: getArtistString(track.artistContribs, { + showContrib: true, + showIcons: true, }), - track.coverArtistContribs.length && language.$('releaseInfo.coverArtBy', { - artists: getArtistString(track.coverArtistContribs, { - showContrib: true, - showIcons: true - }) + }), + track.coverArtistContribs.length && + language.$("releaseInfo.coverArtBy", { + artists: getArtistString( + track.coverArtistContribs, + { + showContrib: true, + showIcons: true, + } + ), + }), + track.date && + language.$("releaseInfo.released", { + date: language.formatDate(track.date), }), - track.date && language.$('releaseInfo.released', { - date: language.formatDate(track.date) + track.coverArtDate && + +track.coverArtDate !== +track.date && + language.$("releaseInfo.artReleased", { + date: language.formatDate(track.coverArtDate), }), - (track.coverArtDate && - +track.coverArtDate !== +track.date && - language.$('releaseInfo.artReleased', { - date: language.formatDate(track.coverArtDate) - })), - track.duration && language.$('releaseInfo.duration', { - duration: language.formatDuration(track.duration) - }) - ].filter(Boolean).join('<br>\n')} + track.duration && + language.$("releaseInfo.duration", { + duration: language.formatDuration( + track.duration + ), + }), + ] + .filter(Boolean) + .join("<br>\n")} </p> <p>${ - (track.urls?.length - ? language.$('releaseInfo.listenOn', { - links: language.formatDisjunctionList(track.urls.map(url => fancifyURL(url, {language}))) - }) - : language.$('releaseInfo.listenOn.noLinks')) + track.urls?.length + ? language.$("releaseInfo.listenOn", { + links: language.formatDisjunctionList( + track.urls.map((url) => + fancifyURL(url, { language }) + ) + ), + }) + : language.$("releaseInfo.listenOn.noLinks") }</p> - ${otherReleases.length && fixWS` - <p>${language.$('releaseInfo.alsoReleasedAs')}</p> + ${ + otherReleases.length && + fixWS` + <p>${language.$("releaseInfo.alsoReleasedAs")}</p> <ul> - ${otherReleases.map(track => fixWS` - <li>${language.$('releaseInfo.alsoReleasedAs.item', { + ${otherReleases + .map( + (track) => fixWS` + <li>${language.$( + "releaseInfo.alsoReleasedAs.item", + { track: link.track(track), - album: link.album(track.album) - })}</li> - `).join('\n')} + album: link.album(track.album), + } + )}</li> + ` + ) + .join("\n")} </ul> - `} - ${track.contributorContribs.length && fixWS` - <p>${language.$('releaseInfo.contributors')}</p> + ` + } + ${ + track.contributorContribs.length && + fixWS` + <p>${language.$("releaseInfo.contributors")}</p> <ul> - ${(track.contributorContribs - .map(contrib => `<li>${getArtistString([contrib], { + ${track.contributorContribs + .map( + (contrib) => + `<li>${getArtistString([contrib], { showContrib: true, - showIcons: true - })}</li>`) - .join('\n'))} + showIcons: true, + })}</li>` + ) + .join("\n")} </ul> - `} - ${referencedTracks.length && fixWS` - <p>${language.$('releaseInfo.tracksReferenced', {track: `<i>${track.name}</i>`})}</p> - ${html.tag('ul', referencedTracks.map(getTrackItem))} - `} - ${referencedByTracks.length && fixWS` - <p>${language.$('releaseInfo.tracksThatReference', {track: `<i>${track.name}</i>`})}</p> - ${generateTrackListDividedByGroups(referencedByTracks, { + ` + } + ${ + referencedTracks.length && + fixWS` + <p>${language.$("releaseInfo.tracksReferenced", { + track: `<i>${track.name}</i>`, + })}</p> + ${html.tag( + "ul", + referencedTracks.map(getTrackItem) + )} + ` + } + ${ + referencedByTracks.length && + fixWS` + <p>${language.$("releaseInfo.tracksThatReference", { + track: `<i>${track.name}</i>`, + })}</p> + ${generateTrackListDividedByGroups( + referencedByTracks, + { getTrackItem, wikiData, - })} - `} - ${wikiInfo.enableFlashesAndGames && flashesThatFeature.length && fixWS` - <p>${language.$('releaseInfo.flashesThatFeature', {track: `<i>${track.name}</i>`})}</p> + } + )} + ` + } + ${ + wikiInfo.enableFlashesAndGames && + flashesThatFeature.length && + fixWS` + <p>${language.$("releaseInfo.flashesThatFeature", { + track: `<i>${track.name}</i>`, + })}</p> <ul> - ${flashesThatFeature.map(({ flash, as }) => html.tag('li', - {class: as !== track && 'rerelease'}, - (as === track - ? language.$('releaseInfo.flashesThatFeature.item', { - flash: link.flash(flash) - }) - : language.$('releaseInfo.flashesThatFeature.item.asDifferentRelease', { - flash: link.flash(flash), - track: link.track(as) - })))).join('\n')} + ${flashesThatFeature + .map(({ flash, as }) => + html.tag( + "li", + { class: as !== track && "rerelease" }, + as === track + ? language.$( + "releaseInfo.flashesThatFeature.item", + { + flash: link.flash(flash), + } + ) + : language.$( + "releaseInfo.flashesThatFeature.item.asDifferentRelease", + { + flash: link.flash(flash), + track: link.track(as), + } + ) + ) + ) + .join("\n")} </ul> - `} - ${track.lyrics && fixWS` - <p>${language.$('releaseInfo.lyrics')}</p> + ` + } + ${ + track.lyrics && + fixWS` + <p>${language.$("releaseInfo.lyrics")}</p> <blockquote> ${transformLyrics(track.lyrics)} </blockquote> - `} - ${hasCommentary && fixWS` - <p>${language.$('releaseInfo.artistCommentary')}</p> + ` + } + ${ + hasCommentary && + fixWS` + <p>${language.$("releaseInfo.artistCommentary")}</p> <blockquote> - ${generateCommentary({link, language, transformMultiline})} + ${generateCommentary({ + link, + language, + transformMultiline, + })} </blockquote> - `} - ` - }, + ` + } + `, + }, - sidebarLeft: generateAlbumSidebar(album, track, { - fancifyURL, - getLinkThemeString, - link, - language, - transformMultiline, - wikiData - }), + sidebarLeft: generateAlbumSidebar(album, track, { + fancifyURL, + getLinkThemeString, + link, + language, + transformMultiline, + wikiData, + }), - nav: { - linkContainerClasses: ['nav-links-hierarchy'], - links: [ - {toHome: true}, - { - path: ['localized.album', album.directory], - title: album.name - }, - listTag === 'ol' ? { - html: language.$('trackPage.nav.track.withNumber', { - number: album.tracks.indexOf(track) + 1, - track: link.track(track, {class: 'current', to}) - }) - } : { - html: language.$('trackPage.nav.track', { - track: link.track(track, {class: 'current', to}) - }) - }, - ].filter(Boolean), - content: generateAlbumChronologyLinks(album, track, {generateChronologyLinks}), - bottomRowContent: (album.tracks.length > 1 && - generateAlbumNavLinks(album, track, { - generatePreviousNextLinks, - language, - })), + nav: { + linkContainerClasses: ["nav-links-hierarchy"], + links: [ + { toHome: true }, + { + path: ["localized.album", album.directory], + title: album.name, + }, + listTag === "ol" + ? { + html: language.$("trackPage.nav.track.withNumber", { + number: album.tracks.indexOf(track) + 1, + track: link.track(track, { class: "current", to }), + }), + } + : { + html: language.$("trackPage.nav.track", { + track: link.track(track, { class: "current", to }), + }), }, + ].filter(Boolean), + content: generateAlbumChronologyLinks(album, track, { + generateChronologyLinks, + }), + bottomRowContent: + album.tracks.length > 1 && + generateAlbumNavLinks(album, track, { + generatePreviousNextLinks, + language, + }), + }, - secondaryNav: generateAlbumSecondaryNav(album, track, { - language, - link, - getLinkThemeString, - }), - }; - } - }; + secondaryNav: generateAlbumSecondaryNav(album, track, { + language, + link, + getLinkThemeString, + }), + }; + }, + }; - return [data, page]; + return [data, page]; } - |