From b2469c03bd4bdb29c5e80752f812203a6755c159 Mon Sep 17 00:00:00 2001
From: "(quasar) nebula"
Date: Fri, 4 Jun 2021 17:30:16 -0300
Subject: move around a bunch of utility functions
---
src/listing-spec.js | 9 +-
src/misc-templates.js | 369 ++++++++++++++++++++++++++++++++++++
src/page/album-commentary.js | 7 +-
src/page/album.js | 275 ++++++++++++++-------------
src/page/flash.js | 7 +-
src/page/group.js | 32 +++-
src/page/homepage.js | 5 +-
src/page/listing.js | 77 ++++----
src/page/tag.js | 5 +-
src/page/track.js | 7 +-
src/upd8.js | 434 +++++++------------------------------------
src/util/colors.js | 28 ---
src/util/link.js | 9 +-
13 files changed, 669 insertions(+), 595 deletions(-)
create mode 100644 src/misc-templates.js
(limited to 'src')
diff --git a/src/listing-spec.js b/src/listing-spec.js
index a5239a41..90a2de5a 100644
--- a/src/listing-spec.js
+++ b/src/listing-spec.js
@@ -1,9 +1,5 @@
import fixWS from 'fix-whitespace';
-import {
- getLinkThemeString
-} from './util/colors.js';
-
import {
UNRELEASED_TRACKS_DIRECTORY
} from './util/magic-constants.js';
@@ -757,7 +753,10 @@ const listingSpec = [
fandomAlbumData: wikiData.fandomAlbumData
}),
- html: ({officialAlbumData, fandomAlbumData}, {strings}) => fixWS`
+ html: ({officialAlbumData, fandomAlbumData}, {
+ getLinkThemeString,
+ strings
+ }) => fixWS`
Choose a link to go to a random page in that category or album! If your browser doesn't support relatively modern JavaScript or you've disabled it, these links won't work - sorry.
(Data files are downloading in the background! Please wait for data to load.)
(Data files have finished being downloaded. The links should work!)
diff --git a/src/misc-templates.js b/src/misc-templates.js
new file mode 100644
index 00000000..d4e4af38
--- /dev/null
+++ b/src/misc-templates.js
@@ -0,0 +1,369 @@
+// Miscellaneous utility functions which are useful across page specifications.
+// These are made available right on a page spec's ({wikiData, strings, ...})
+// args object!
+
+import fixWS from 'fix-whitespace';
+
+import * as html from './util/html.js';
+
+import {
+ getColors
+} from './util/colors.js';
+
+import {
+ UNRELEASED_TRACKS_DIRECTORY
+} from './util/magic-constants.js';
+
+import {
+ unique
+} from './util/sugar.js';
+
+import {
+ getTotalDuration,
+ sortByDate
+} from './util/wiki-data.js';
+
+// Artist strings
+
+export function getArtistString(artists, {
+ iconifyURL, link, strings,
+ showIcons = false,
+ showContrib = false
+}) {
+ return strings.list.and(artists.map(({ who, what }) => {
+ const { urls, directory, name } = who;
+ return [
+ link.artist(who),
+ showContrib && what && `(${what})`,
+ showIcons && urls.length && `(${
+ strings.list.unit(urls.map(url => iconifyURL(url, {strings})))
+ }) `
+ ].filter(Boolean).join(' ');
+ }));
+}
+
+// Chronology links
+
+export function generateChronologyLinks(currentThing, {
+ contribKey,
+ getThings,
+ headingString,
+ link,
+ linkAnythingMan,
+ strings,
+ wikiData
+}) {
+ const { albumData } = wikiData;
+
+ const contributions = currentThing[contribKey];
+ if (!contributions) {
+ return '';
+ }
+
+ if (contributions.length > 8) {
+ return `${strings('misc.chronology.seeArtistPages')}
`;
+ }
+
+ return contributions.map(({ who: artist }) => {
+ const things = sortByDate(unique(getThings(artist)));
+ const releasedThings = things.filter(thing => {
+ const album = albumData.includes(thing) ? thing : thing.album;
+ return !(album && album.directory === UNRELEASED_TRACKS_DIRECTORY);
+ });
+ const index = releasedThings.indexOf(currentThing);
+
+ if (index === -1) return '';
+
+ // TODO: This can pro8a8ly 8e made to use generatePreviousNextLinks?
+ // We'd need to make generatePreviousNextLinks use toAnythingMan tho.
+ const previous = releasedThings[index - 1];
+ const next = releasedThings[index + 1];
+ const parts = [
+ previous && linkAnythingMan(previous, {
+ color: false,
+ text: strings('misc.nav.previous')
+ }),
+ next && linkAnythingMan(next, {
+ color: false,
+ text: strings('misc.nav.next')
+ })
+ ].filter(Boolean);
+
+ const stringOpts = {
+ index: strings.count.index(index + 1, {strings}),
+ artist: link.artist(artist)
+ };
+
+ return fixWS`
+
+ ${strings(headingString, stringOpts)}
+ ${parts.length && `(${parts.join(', ')}) `}
+
+ `;
+ }).filter(Boolean).join('\n');
+}
+
+// Content warning tags
+
+export function getRevealStringFromWarnings(warnings, {strings}) {
+ return strings('misc.contentWarnings', {warnings}) + `${strings('misc.contentWarnings.reveal')} `
+}
+
+export function getRevealStringFromTags(tags, {strings}) {
+ return tags && tags.some(tag => tag.isCW) && (
+ getRevealStringFromWarnings(strings.list.unit(tags.filter(tag => tag.isCW).map(tag => tag.name)), {strings}));
+}
+
+// Cover art links
+
+export function generateCoverLink({
+ img, link, strings, to, wikiData,
+ src,
+ path,
+ alt,
+ tags = []
+}) {
+ const { wikiInfo } = wikiData;
+
+ if (!src && path) {
+ src = to(...path);
+ }
+
+ if (!src) {
+ throw new Error(`Expected src or path`);
+ }
+
+ return fixWS`
+
+ ${img({
+ src,
+ alt,
+ thumb: 'medium',
+ id: 'cover-art',
+ link: true,
+ square: true,
+ reveal: getRevealStringFromTags(tags, {strings})
+ })}
+ ${wikiInfo.features.artTagUI && tags.filter(tag => !tag.isCW).length && fixWS`
+
+ ${strings('releaseInfo.artTags')}
+ ${(tags
+ .filter(tag => !tag.isCW)
+ .map(link.tag)
+ .join(',\n'))}
+
+ `}
+
+ `;
+}
+
+// CSS & color shenanigans
+
+export function getThemeString(color, additionalVariables = []) {
+ if (!color) return '';
+
+ const { primary, dim, bg } = getColors(color);
+
+ const variables = [
+ `--primary-color: ${primary}`,
+ `--dim-color: ${dim}`,
+ `--bg-color: ${bg}`,
+ ...additionalVariables
+ ].filter(Boolean);
+
+ if (!variables.length) return '';
+
+ return (
+ `:root {\n` +
+ variables.map(line => ` ` + line + ';\n').join('') +
+ `}`
+ );
+}
+export function getAlbumStylesheet(album, {to}) {
+ return [
+ album.wallpaperArtists && fixWS`
+ body::before {
+ background-image: url("${to('media.albumWallpaper', album.directory)}");
+ ${album.wallpaperStyle}
+ }
+ `,
+ album.bannerStyle && fixWS`
+ #banner img {
+ ${album.bannerStyle}
+ }
+ `
+ ].filter(Boolean).join('\n');
+}
+
+// Fancy lookin' links
+
+export function fancifyURL(url, {strings, album = false} = {}) {
+ const domain = new URL(url).hostname;
+ return fixWS`${
+ domain.includes('bandcamp.com') ? strings('misc.external.bandcamp') :
+ [
+ 'music.solatrux.com'
+ ].includes(domain) ? strings('misc.external.bandcamp.domain', {domain}) :
+ [
+ 'types.pl'
+ ].includes(domain) ? strings('misc.external.mastodon.domain', {domain}) :
+ domain.includes('youtu') ? (album
+ ? (url.includes('list=')
+ ? strings('misc.external.youtube.playlist')
+ : strings('misc.external.youtube.fullAlbum'))
+ : strings('misc.external.youtube')) :
+ domain.includes('soundcloud') ? strings('misc.external.soundcloud') :
+ domain.includes('tumblr.com') ? strings('misc.external.tumblr') :
+ domain.includes('twitter.com') ? strings('misc.external.twitter') :
+ domain.includes('deviantart.com') ? strings('misc.external.deviantart') :
+ domain.includes('wikipedia.org') ? strings('misc.external.wikipedia') :
+ domain.includes('poetryfoundation.org') ? strings('misc.external.poetryFoundation') :
+ domain.includes('instagram.com') ? strings('misc.external.instagram') :
+ domain.includes('patreon.com') ? strings('misc.external.patreon') :
+ domain
+ } `;
+}
+
+export function fancifyFlashURL(url, flash, {strings}) {
+ const link = fancifyURL(url, {strings});
+ return `${
+ url.includes('homestuck.com') ? (isNaN(Number(flash.page))
+ ? strings('misc.external.flash.homestuck.secret', {link})
+ : strings('misc.external.flash.homestuck.page', {link, page: flash.page})) :
+ url.includes('bgreco.net') ? strings('misc.external.flash.bgreco', {link}) :
+ url.includes('youtu') ? strings('misc.external.flash.youtube', {link}) :
+ link
+ } `;
+}
+
+export function iconifyURL(url, {strings, to}) {
+ const domain = new URL(url).hostname;
+ const [ id, msg ] = (
+ domain.includes('bandcamp.com') ? ['bandcamp', strings('misc.external.bandcamp')] :
+ (
+ domain.includes('music.solatrus.com')
+ ) ? ['bandcamp', strings('misc.external.bandcamp.domain', {domain})] :
+ (
+ domain.includes('types.pl')
+ ) ? ['mastodon', strings('misc.external.mastodon.domain', {domain})] :
+ domain.includes('youtu') ? ['youtube', strings('misc.external.youtube')] :
+ domain.includes('soundcloud') ? ['soundcloud', strings('misc.external.soundcloud')] :
+ domain.includes('tumblr.com') ? ['tumblr', strings('misc.external.tumblr')] :
+ domain.includes('twitter.com') ? ['twitter', strings('misc.external.twitter')] :
+ domain.includes('deviantart.com') ? ['deviantart', strings('misc.external.deviantart')] :
+ domain.includes('instagram.com') ? ['instagram', strings('misc.external.bandcamp')] :
+ ['globe', strings('misc.external.domain', {domain})]
+ );
+ return fixWS`${msg} `;
+}
+
+// Grids
+
+export function getGridHTML({
+ getLinkThemeString,
+ img,
+ strings,
+
+ entries,
+ srcFn,
+ hrefFn,
+ altFn = () => '',
+ detailsFn = null,
+ lazy = true
+}) {
+ return entries.map(({ large, item }, i) => html.tag('a',
+ {
+ class: ['grid-item', 'box', large && 'large-grid-item'],
+ href: hrefFn(item),
+ style: getLinkThemeString(item.color)
+ },
+ fixWS`
+ ${img({
+ src: srcFn(item),
+ alt: altFn(item),
+ thumb: 'small',
+ lazy: (typeof lazy === 'number' ? i >= lazy : lazy),
+ square: true,
+ reveal: getRevealStringFromTags(item.artTags, {strings})
+ })}
+ ${item.name}
+ ${detailsFn && `${detailsFn(item)} `}
+ `)).join('\n');
+}
+
+export function getAlbumGridHTML({
+ getAlbumCover, getGridHTML, strings, to,
+ details = false,
+ ...props
+}) {
+ return getGridHTML({
+ srcFn: getAlbumCover,
+ hrefFn: album => to('localized.album', album.directory),
+ detailsFn: details && (album => strings('misc.albumGridDetails', {
+ tracks: strings.count.tracks(album.tracks.length, {unit: true}),
+ time: strings.count.duration(getTotalDuration(album.tracks))
+ })),
+ ...props
+ });
+}
+
+export function getFlashGridHTML({
+ getFlashCover, getGridHTML, to,
+ ...props
+}) {
+ return getGridHTML({
+ srcFn: getFlashCover,
+ hrefFn: flash => to('localized.flash', flash.directory),
+ ...props
+ });
+}
+// Nav-bar links
+
+export function generateInfoGalleryLinks(currentThing, isGallery, {
+ link, strings,
+ linkKeyGallery,
+ linkKeyInfo
+}) {
+ return [
+ link[linkKeyInfo](currentThing, {
+ class: isGallery ? '' : 'current',
+ text: strings('misc.nav.info')
+ }),
+ link[linkKeyGallery](currentThing, {
+ class: isGallery ? 'current' : '',
+ text: strings('misc.nav.gallery')
+ })
+ ].join(', ');
+}
+
+export function generatePreviousNextLinks(current, {
+ data,
+ link,
+ linkKey,
+ strings
+}) {
+ const linkFn = link[linkKey];
+
+ const index = data.indexOf(current);
+ const previous = data[index - 1];
+ const next = data[index + 1];
+
+ return [
+ previous && linkFn(previous, {
+ attributes: {
+ id: 'previous-button',
+ title: previous.name
+ },
+ text: strings('misc.nav.previous'),
+ color: false
+ }),
+ next && linkFn(next, {
+ attributes: {
+ id: 'next-button',
+ title: next.name
+ },
+ text: strings('misc.nav.next'),
+ color: false
+ })
+ ].filter(Boolean).join(', ');
+}
diff --git a/src/page/album-commentary.js b/src/page/album-commentary.js
index 77ca3ef1..c03ae3db 100644
--- a/src/page/album-commentary.js
+++ b/src/page/album-commentary.js
@@ -4,11 +4,6 @@
import fixWS from 'fix-whitespace';
-import {
- getLinkThemeString,
- getThemeString
-} from '../util/colors.js';
-
import {
filterAlbumsByCommentary
} from '../util/wiki-data.js';
@@ -34,6 +29,8 @@ export function write(album, {wikiData}) {
path: ['albumCommentary', album.directory],
page: ({
getAlbumStylesheet,
+ getLinkThemeString,
+ getThemeString,
link,
strings,
to,
diff --git a/src/page/album.js b/src/page/album.js
index 16da6021..adcc0584 100644
--- a/src/page/album.js
+++ b/src/page/album.js
@@ -4,13 +4,12 @@
import fixWS from 'fix-whitespace';
-import {
- getLinkThemeString,
- getThemeString
-} from '../util/colors.js';
-
import * as html from '../util/html.js';
+import {
+ bindOpts
+} from '../util/sugar.js';
+
import {
getAlbumCover,
getAlbumListTag,
@@ -26,7 +25,12 @@ export function targets({wikiData}) {
export function write(album, {wikiData}) {
const { wikiInfo } = wikiData;
- const trackToListItem = (track, {getArtistString, link, strings}) => {
+ const unbound_trackToListItem = (track, {
+ getArtistString,
+ getLinkThemeString,
+ link,
+ strings
+ }) => {
const itemOpts = {
duration: strings.count.duration(track.duration),
track: link.track(track)
@@ -96,140 +100,152 @@ export function write(album, {wikiData}) {
generateCoverLink,
getAlbumStylesheet,
getArtistString,
+ getLinkThemeString,
+ getThemeString,
link,
strings,
transformMultiline
- }) => ({
- title: strings('albumPage.title', {album: album.name}),
- stylesheet: getAlbumStylesheet(album),
- theme: getThemeString(album.color, [
- `--album-directory: ${album.directory}`
- ]),
+ }) => {
+ const trackToListItem = bindOpts(unbound_trackToListItem, {
+ getArtistString,
+ getLinkThemeString,
+ link,
+ strings
+ });
- banner: album.bannerArtists && {
- dimensions: album.bannerDimensions,
- path: ['media.albumBanner', album.directory],
- alt: strings('misc.alt.albumBanner'),
- position: 'top'
- },
+ return {
+ title: strings('albumPage.title', {album: album.name}),
+ stylesheet: getAlbumStylesheet(album),
+ theme: getThemeString(album.color, [
+ `--album-directory: ${album.directory}`
+ ]),
- main: {
- content: fixWS`
- ${generateCoverLink({
- path: ['media.albumCover', album.directory],
- alt: strings('misc.alt.albumCover'),
- tags: album.artTags
- })}
- ${strings('albumPage.title', {album: album.name})}
-
- ${[
- album.artists && strings('releaseInfo.by', {
- artists: getArtistString(album.artists, {
- showContrib: true,
- showIcons: true
- })
- }),
- album.coverArtists && strings('releaseInfo.coverArtBy', {
- artists: getArtistString(album.coverArtists, {
- showContrib: true,
- showIcons: true
- })
- }),
- album.wallpaperArtists && strings('releaseInfo.wallpaperArtBy', {
- artists: getArtistString(album.wallpaperArtists, {
- showContrib: true,
- showIcons: true
+ banner: album.bannerArtists && {
+ dimensions: album.bannerDimensions,
+ path: ['media.albumBanner', album.directory],
+ alt: strings('misc.alt.albumBanner'),
+ position: 'top'
+ },
+
+ main: {
+ content: fixWS`
+ ${generateCoverLink({
+ path: ['media.albumCover', album.directory],
+ alt: strings('misc.alt.albumCover'),
+ tags: album.artTags
+ })}
+
${strings('albumPage.title', {album: album.name})}
+
+ ${[
+ album.artists && strings('releaseInfo.by', {
+ artists: getArtistString(album.artists, {
+ showContrib: true,
+ showIcons: true
+ })
+ }),
+ album.coverArtists && strings('releaseInfo.coverArtBy', {
+ artists: getArtistString(album.coverArtists, {
+ showContrib: true,
+ showIcons: true
+ })
+ }),
+ album.wallpaperArtists && strings('releaseInfo.wallpaperArtBy', {
+ artists: getArtistString(album.wallpaperArtists, {
+ showContrib: true,
+ showIcons: true
+ })
+ }),
+ album.bannerArtists && strings('releaseInfo.bannerArtBy', {
+ artists: getArtistString(album.bannerArtists, {
+ showContrib: true,
+ showIcons: true
+ })
+ }),
+ strings('releaseInfo.released', {
+ date: strings.count.date(album.date)
+ }),
+ +album.coverArtDate !== +album.date && strings('releaseInfo.artReleased', {
+ date: strings.count.date(album.coverArtDate)
+ }),
+ strings('releaseInfo.duration', {
+ duration: strings.count.duration(albumDuration, {approximate: album.tracks.length > 1})
})
- }),
- album.bannerArtists && strings('releaseInfo.bannerArtBy', {
- artists: getArtistString(album.bannerArtists, {
- showContrib: true,
- showIcons: true
+ ].filter(Boolean).join(' \n')}
+
+ ${commentaryEntries && `${
+ strings('releaseInfo.viewCommentary', {
+ link: link.albumCommentary(album, {
+ text: strings('releaseInfo.viewCommentary.link')
})
- }),
- strings('releaseInfo.released', {
- date: strings.count.date(album.date)
- }),
- +album.coverArtDate !== +album.date && strings('releaseInfo.artReleased', {
- date: strings.count.date(album.coverArtDate)
- }),
- strings('releaseInfo.duration', {
- duration: strings.count.duration(albumDuration, {approximate: album.tracks.length > 1})
- })
- ].filter(Boolean).join(' \n')}
-
- ${commentaryEntries && `${
- strings('releaseInfo.viewCommentary', {
- link: link.albumCommentary(album, {
- text: strings('releaseInfo.viewCommentary.link')
})
- })
- }
`}
- ${album.urls.length && `${
- strings('releaseInfo.listenOn', {
- links: strings.list.or(album.urls.map(url => fancifyURL(url, {album: true})))
- })
- }
`}
- ${album.trackGroups ? fixWS`
-
- ${album.trackGroups.map(({ name, color, startIndex, tracks }) => fixWS`
- ${
- strings('trackList.group', {
- duration: strings.count.duration(getTotalDuration(tracks), {approximate: tracks.length > 1}),
- group: name
- })
- }
- <${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}>
- ${tracks.map(t => trackToListItem(t, {getArtistString, link, strings})).join('\n')}
- ${listTag}>
- `).join('\n')}
-
- ` : fixWS`
- <${listTag}>
- ${album.tracks.map(t => trackToListItem(t, {getArtistString, link, strings})).join('\n')}
- ${listTag}>
- `}
-
- ${[
- strings('releaseInfo.addedToWiki', {
- date: strings.count.date(album.dateAdded)
+ }
`}
+ ${album.urls.length && `${
+ strings('releaseInfo.listenOn', {
+ links: strings.list.or(album.urls.map(url => fancifyURL(url, {album: true})))
})
- ].filter(Boolean).join(' \n')}
-
- ${album.commentary && fixWS`
- ${strings('releaseInfo.artistCommentary')}
-
- ${transformMultiline(album.commentary)}
-
- `}
- `
- },
+ }
`}
+ ${album.trackGroups ? fixWS`
+
+ ${album.trackGroups.map(({ name, color, startIndex, tracks }) => fixWS`
+ ${
+ strings('trackList.group', {
+ duration: strings.count.duration(getTotalDuration(tracks), {approximate: tracks.length > 1}),
+ group: name
+ })
+ }
+ <${listTag === 'ol' ? `ol start="${startIndex + 1}"` : listTag}>
+ ${tracks.map(trackToListItem).join('\n')}
+ ${listTag}>
+ `).join('\n')}
+
+ ` : fixWS`
+ <${listTag}>
+ ${album.tracks.map(trackToListItem).join('\n')}
+ ${listTag}>
+ `}
+
+ ${[
+ strings('releaseInfo.addedToWiki', {
+ date: strings.count.date(album.dateAdded)
+ })
+ ].filter(Boolean).join(' \n')}
+
+ ${album.commentary && fixWS`
+ ${strings('releaseInfo.artistCommentary')}
+
+ ${transformMultiline(album.commentary)}
+
+ `}
+ `
+ },
- sidebarLeft: generateAlbumSidebar(album, null, {
- fancifyURL,
- link,
- strings,
- transformMultiline,
- wikiData
- }),
+ sidebarLeft: generateAlbumSidebar(album, null, {
+ fancifyURL,
+ getLinkThemeString,
+ link,
+ strings,
+ transformMultiline,
+ wikiData
+ }),
- nav: {
- links: [
- {toHome: true},
- {
- html: strings('albumPage.nav.album', {
- album: link.album(album, {class: 'current'})
- })
- },
- album.tracks.length > 1 &&
- {
- divider: false,
- html: generateAlbumNavLinks(album, null, {strings})
- }
- ],
- content: html.tag('div', generateAlbumChronologyLinks(album, null, {generateChronologyLinks}))
- }
- })
+ nav: {
+ links: [
+ {toHome: true},
+ {
+ html: strings('albumPage.nav.album', {
+ album: link.album(album, {class: 'current'})
+ })
+ },
+ album.tracks.length > 1 &&
+ {
+ divider: false,
+ html: generateAlbumNavLinks(album, null, {strings})
+ }
+ ],
+ content: html.tag('div', generateAlbumChronologyLinks(album, null, {generateChronologyLinks}))
+ }
+ };
+ }
};
return [page, data];
@@ -239,6 +255,7 @@ export function write(album, {wikiData}) {
export function generateAlbumSidebar(album, currentTrack, {
fancifyURL,
+ getLinkThemeString,
link,
strings,
transformMultiline,
diff --git a/src/page/flash.js b/src/page/flash.js
index 4ffaefc6..9c59016d 100644
--- a/src/page/flash.js
+++ b/src/page/flash.js
@@ -4,11 +4,6 @@
import fixWS from 'fix-whitespace';
-import {
- getLinkThemeString,
- getThemeString
-} from '../util/colors.js';
-
import * as html from '../util/html.js';
import {
@@ -36,6 +31,7 @@ export function write(flash, {wikiData}) {
generatePreviousNextLinks,
getArtistString,
getFlashCover,
+ getThemeString,
link,
strings,
transformInline
@@ -118,6 +114,7 @@ export function writeTargetless({wikiData}) {
path: ['flashIndex'],
page: ({
getFlashGridHTML,
+ getLinkThemeString,
link,
strings
}) => ({
diff --git a/src/page/group.js b/src/page/group.js
index 5db5a8ff..698c17ec 100644
--- a/src/page/group.js
+++ b/src/page/group.js
@@ -8,11 +8,6 @@ import {
UNRELEASED_TRACKS_DIRECTORY
} from '../util/magic-constants.js';
-import {
- getLinkThemeString,
- getThemeString
-} from '../util/colors.js';
-
import * as html from '../util/html.js';
import {
@@ -44,6 +39,8 @@ export function write(group, {wikiData}) {
page: ({
generateInfoGalleryLinks,
generatePreviousNextLinks,
+ getLinkThemeString,
+ getThemeString,
fancifyURL,
link,
strings,
@@ -92,7 +89,13 @@ export function write(group, {wikiData}) {
`
},
- sidebarLeft: generateGroupSidebar(group, false, {link, strings, wikiData}),
+ sidebarLeft: generateGroupSidebar(group, false, {
+ getLinkThemeString,
+ link,
+ strings,
+ wikiData
+ }),
+
nav: generateGroupNav(group, false, {
generateInfoGalleryLinks,
generatePreviousNextLinks,
@@ -110,6 +113,8 @@ export function write(group, {wikiData}) {
generateInfoGalleryLinks,
generatePreviousNextLinks,
getAlbumGridHTML,
+ getLinkThemeString,
+ getThemeString,
link,
strings
}) => ({
@@ -144,7 +149,13 @@ export function write(group, {wikiData}) {
`
},
- sidebarLeft: generateGroupSidebar(group, true, {link, strings, wikiData}),
+ sidebarLeft: generateGroupSidebar(group, true, {
+ getLinkThemeString,
+ link,
+ strings,
+ wikiData
+ }),
+
nav: generateGroupNav(group, true, {
generateInfoGalleryLinks,
generatePreviousNextLinks,
@@ -160,7 +171,12 @@ export function write(group, {wikiData}) {
// Utility functions
-function generateGroupSidebar(currentGroup, isGallery, {link, strings, wikiData}) {
+function generateGroupSidebar(currentGroup, isGallery, {
+ getLinkThemeString,
+ link,
+ strings,
+ wikiData
+}) {
const { groupCategoryData, wikiInfo } = wikiData;
if (!wikiInfo.features.groupUI) {
diff --git a/src/page/homepage.js b/src/page/homepage.js
index d1dcc680..37ec4426 100644
--- a/src/page/homepage.js
+++ b/src/page/homepage.js
@@ -4,10 +4,6 @@
import fixWS from 'fix-whitespace';
-import {
- getLinkThemeString
-} from '../util/colors.js';
-
import find from '../util/find.js';
import * as html from '../util/html.js';
@@ -27,6 +23,7 @@ export function writeTargetless({wikiData}) {
path: ['home'],
page: ({
getAlbumGridHTML,
+ getLinkThemeString,
link,
strings,
to,
diff --git a/src/page/listing.js b/src/page/listing.js
index b0766b28..d4021747 100644
--- a/src/page/listing.js
+++ b/src/page/listing.js
@@ -46,44 +46,45 @@ export function write(listing, {wikiData}) {
const page = {
type: 'page',
path: ['listing', listing.directory],
- page: ({
- link,
- strings
- }) => ({
- title: listing.title({strings}),
-
- main: {
- content: fixWS`
- ${listing.title({strings})}
- ${listing.html && (listing.data
- ? listing.html(data, {link, strings})
- : listing.html({link, strings}))}
- ${listing.row && fixWS`
-
- ${(data
- .map(item => listing.row(item, {link, strings}))
- .map(row => `${row} `)
- .join('\n'))}
-
- `}
- `
- },
-
- sidebarLeft: {
- content: generateSidebarForListings(listing, {link, strings, wikiData})
- },
-
- nav: {
- links: [
- {toHome: true},
- {
- path: ['localized.listingIndex'],
- title: strings('listingIndex.title')
- },
- {toCurrentPage: true}
- ]
- }
- })
+ page: opts => {
+ const { link, strings } = opts;
+
+ return {
+ title: listing.title({strings}),
+
+ main: {
+ content: fixWS`
+ ${listing.title({strings})}
+ ${listing.html && (listing.data
+ ? listing.html(data, opts)
+ : listing.html(opts))}
+ ${listing.row && fixWS`
+
+ ${(data
+ .map(item => listing.row(item, opts))
+ .map(row => `${row} `)
+ .join('\n'))}
+
+ `}
+ `
+ },
+
+ sidebarLeft: {
+ content: generateSidebarForListings(listing, {link, strings, wikiData})
+ },
+
+ nav: {
+ links: [
+ {toHome: true},
+ {
+ path: ['localized.listingIndex'],
+ title: strings('listingIndex.title')
+ },
+ {toCurrentPage: true}
+ ]
+ }
+ };
+ }
};
return [page];
diff --git a/src/page/tag.js b/src/page/tag.js
index c6f64bfc..610f4665 100644
--- a/src/page/tag.js
+++ b/src/page/tag.js
@@ -4,10 +4,6 @@
import fixWS from 'fix-whitespace';
-import {
- getThemeString
-} from '../util/colors.js';
-
// Page exports
export function condition({wikiData}) {
@@ -28,6 +24,7 @@ export function write(tag, {wikiData}) {
page: ({
getAlbumCover,
getGridHTML,
+ getThemeString,
getTrackCover,
link,
strings,
diff --git a/src/page/track.js b/src/page/track.js
index 2dec9bd3..0941ee89 100644
--- a/src/page/track.js
+++ b/src/page/track.js
@@ -10,10 +10,6 @@ import {
generateAlbumSidebar
} from './album.js';
-import {
- getThemeString
-} from '../util/colors.js';
-
import * as html from '../util/html.js';
import {
@@ -134,6 +130,8 @@ export function write(track, {wikiData}) {
generatePreviousNextLinks,
getAlbumStylesheet,
getArtistString,
+ getLinkThemeString,
+ getThemeString,
getTrackCover,
link,
strings,
@@ -284,6 +282,7 @@ export function write(track, {wikiData}) {
sidebarLeft: generateAlbumSidebar(album, track, {
fancifyURL,
+ getLinkThemeString,
link,
strings,
transformMultiline,
diff --git a/src/upd8.js b/src/upd8.js
index 345f166b..8652f65c 100755
--- a/src/upd8.js
+++ b/src/upd8.js
@@ -116,7 +116,25 @@ import * as pageSpecs from './page/index.js';
import find from './util/find.js';
import * as html from './util/html.js';
-import unbound_link from './util/link.js';
+import unbound_link, {getLinkThemeString} from './util/link.js';
+
+import {
+ fancifyFlashURL,
+ fancifyURL,
+ generateChronologyLinks,
+ generateCoverLink,
+ generateInfoGalleryLinks,
+ generatePreviousNextLinks,
+ getAlbumGridHTML,
+ getAlbumStylesheet,
+ getArtistString,
+ getFlashGridHTML,
+ getGridHTML,
+ getRevealStringFromTags,
+ getRevealStringFromWarnings,
+ getThemeString,
+ iconifyURL
+} from './misc-templates.js';
import {
decorateTime,
@@ -127,11 +145,6 @@ import {
progressPromiseAll
} from './util/cli.js';
-import {
- getLinkThemeString,
- getThemeString
-} from './util/colors.js';
-
import {
validateReplacerSpec,
transformInline
@@ -1761,51 +1774,43 @@ writePage.html = (pageFn, {
const collapseSidebars = (sidebarLeft.collapse !== false) && (sidebarRight.collapse !== false);
- const mainHTML = main.content && fixWS`
-
- ${main.content}
-
- `;
+ const mainHTML = main.content && html.tag('main', {
+ id: 'content',
+ class: main.classes
+ }, main.content);
- const footerHTML = footer.content && fixWS`
-
- `;
+ const footerHTML = footer.content && html.tag('footer', {
+ id: 'footer',
+ class: footer.classes
+ }, footer.content);
const generateSidebarHTML = (id, {
content,
multiple,
- classes: sidebarClasses = [],
+ classes,
collapse = true,
wide = false
- }) => (content ? fixWS`
-
- ${content}
-
- ` : multiple ? fixWS`
-
- ${multiple.map(content => fixWS`
-
- ${content}
-
- `).join('\n')}
-
- ` : '');
+ }) => (content
+ ? html.tag('div',
+ {id, class: [
+ 'sidebar-column',
+ 'sidebar',
+ wide && 'wide',
+ !collapse && 'no-hide',
+ ...classes
+ ]},
+ content)
+ : multiple ? html.tag('div',
+ {id, class: [
+ 'sidebar-column',
+ 'sidebar-multiple',
+ wide && 'wide',
+ !collapse && 'no-hide'
+ ]},
+ multiple.map(content => html.tag('div',
+ {class: ['sidebar', ...classes]},
+ content)))
+ : '');
const sidebarLeftHTML = generateSidebarHTML('sidebar-left', sidebarLeft);
const sidebarRightHTML = generateSidebarHTML('sidebar-right', sidebarRight);
@@ -2012,58 +2017,6 @@ writePage.paths = (baseDirectory, fullKey, directory = '', {
};
};
-function getGridHTML({
- strings,
- entries,
- srcFn,
- hrefFn,
- altFn = () => '',
- detailsFn = null,
- lazy = true
-}) {
- return entries.map(({ large, item }, i) => fixWS`
-
- ${img({
- src: srcFn(item),
- alt: altFn(item),
- thumb: 'small',
- lazy: (typeof lazy === 'number' ? i >= lazy : lazy),
- square: true,
- reveal: getRevealStringFromTags(item.artTags, {strings})
- })}
- ${item.name}
- ${detailsFn && `${detailsFn(item)} `}
-
- `).join('\n');
-}
-
-function getAlbumGridHTML({
- getAlbumCover, getGridHTML, strings, to,
- details = false,
- ...props
-}) {
- return getGridHTML({
- srcFn: getAlbumCover,
- hrefFn: album => to('localized.album', album.directory),
- detailsFn: details && (album => strings('misc.albumGridDetails', {
- tracks: strings.count.tracks(album.tracks.length, {unit: true}),
- time: strings.count.duration(getTotalDuration(album.tracks))
- })),
- ...props
- });
-}
-
-function getFlashGridHTML({
- getFlashCover, getGridHTML, to,
- ...props
-}) {
- return getGridHTML({
- srcFn: getFlashCover,
- hrefFn: flash => to('localized.flash', flash.directory),
- ...props
- });
-}
-
function writeSymlinks() {
return progressPromiseAll('Writing site symlinks.', [
link(path.join(__dirname, UTILITY_DIRECTORY), 'shared.utilityRoot'),
@@ -2115,72 +2068,6 @@ function writeSharedFilesAndPages({strings, wikiData}) {
].filter(Boolean));
}
-function getRevealStringFromWarnings(warnings, {strings}) {
- return strings('misc.contentWarnings', {warnings}) + `${strings('misc.contentWarnings.reveal')} `
-}
-
-function getRevealStringFromTags(tags, {strings}) {
- return tags && tags.some(tag => tag.isCW) && (
- getRevealStringFromWarnings(strings.list.unit(tags.filter(tag => tag.isCW).map(tag => tag.name)), {strings}));
-}
-
-function generateCoverLink({
- link, strings, to, wikiData,
- src,
- path,
- alt,
- tags = []
-}) {
- const { wikiInfo } = wikiData;
-
- if (!src && path) {
- src = to(...path);
- }
-
- if (!src) {
- throw new Error(`Expected src or path`);
- }
-
- return fixWS`
-
- ${img({
- src,
- alt,
- thumb: 'medium',
- id: 'cover-art',
- link: true,
- square: true,
- reveal: getRevealStringFromTags(tags, {strings})
- })}
- ${wikiInfo.features.artTagUI && tags.filter(tag => !tag.isCW).length && fixWS`
-
- ${strings('releaseInfo.artTags')}
- ${(tags
- .filter(tag => !tag.isCW)
- .map(link.tag)
- .join(',\n'))}
-
- `}
-
- `;
-}
-
-function getAlbumStylesheet(album, {to}) {
- return [
- album.wallpaperArtists && fixWS`
- body::before {
- background-image: url("${to('media.albumWallpaper', album.directory)}");
- ${album.wallpaperStyle}
- }
- `,
- album.bannerStyle && fixWS`
- #banner img {
- ${album.bannerStyle}
- }
- `
- ].filter(Boolean).join('\n');
-}
-
function generateRedirectPage(title, target, {strings}) {
return fixWS`
@@ -2204,203 +2091,6 @@ function generateRedirectPage(title, target, {strings}) {
`;
}
-function getArtistString(artists, {
- iconifyURL, link, strings,
- showIcons = false,
- showContrib = false
-}) {
- return strings.list.and(artists.map(({ who, what }) => {
- const { urls, directory, name } = who;
- return [
- link.artist(who),
- showContrib && what && `(${what})`,
- showIcons && urls.length && `(${
- strings.list.unit(urls.map(url => iconifyURL(url, {strings})))
- }) `
- ].filter(Boolean).join(' ');
- }));
-}
-
-function getFlashDirectory(flash) {
- // const kebab = getKebabCase(flash.name.replace('[S] ', ''));
- // return flash.page + (kebab ? '-' + kebab : '');
- // return '' + flash.page;
- return '' + flash.directory;
-}
-
-function getTagDirectory({name}) {
- return getKebabCase(name);
-}
-
-function fancifyURL(url, {strings, album = false} = {}) {
- const domain = new URL(url).hostname;
- return fixWS`${
- domain.includes('bandcamp.com') ? strings('misc.external.bandcamp') :
- [
- 'music.solatrux.com'
- ].includes(domain) ? strings('misc.external.bandcamp.domain', {domain}) :
- [
- 'types.pl'
- ].includes(domain) ? strings('misc.external.mastodon.domain', {domain}) :
- domain.includes('youtu') ? (album
- ? (url.includes('list=')
- ? strings('misc.external.youtube.playlist')
- : strings('misc.external.youtube.fullAlbum'))
- : strings('misc.external.youtube')) :
- domain.includes('soundcloud') ? strings('misc.external.soundcloud') :
- domain.includes('tumblr.com') ? strings('misc.external.tumblr') :
- domain.includes('twitter.com') ? strings('misc.external.twitter') :
- domain.includes('deviantart.com') ? strings('misc.external.deviantart') :
- domain.includes('wikipedia.org') ? strings('misc.external.wikipedia') :
- domain.includes('poetryfoundation.org') ? strings('misc.external.poetryFoundation') :
- domain.includes('instagram.com') ? strings('misc.external.instagram') :
- domain.includes('patreon.com') ? strings('misc.external.patreon') :
- domain
- } `;
-}
-
-function fancifyFlashURL(url, flash, {strings}) {
- const link = fancifyURL(url, {strings});
- return `${
- url.includes('homestuck.com') ? (isNaN(Number(flash.page))
- ? strings('misc.external.flash.homestuck.secret', {link})
- : strings('misc.external.flash.homestuck.page', {link, page: flash.page})) :
- url.includes('bgreco.net') ? strings('misc.external.flash.bgreco', {link}) :
- url.includes('youtu') ? strings('misc.external.flash.youtube', {link}) :
- link
- } `;
-}
-
-function iconifyURL(url, {strings, to}) {
- const domain = new URL(url).hostname;
- const [ id, msg ] = (
- domain.includes('bandcamp.com') ? ['bandcamp', strings('misc.external.bandcamp')] :
- (
- domain.includes('music.solatrus.com')
- ) ? ['bandcamp', strings('misc.external.bandcamp.domain', {domain})] :
- (
- domain.includes('types.pl')
- ) ? ['mastodon', strings('misc.external.mastodon.domain', {domain})] :
- domain.includes('youtu') ? ['youtube', strings('misc.external.youtube')] :
- domain.includes('soundcloud') ? ['soundcloud', strings('misc.external.soundcloud')] :
- domain.includes('tumblr.com') ? ['tumblr', strings('misc.external.tumblr')] :
- domain.includes('twitter.com') ? ['twitter', strings('misc.external.twitter')] :
- domain.includes('deviantart.com') ? ['deviantart', strings('misc.external.deviantart')] :
- domain.includes('instagram.com') ? ['instagram', strings('misc.external.bandcamp')] :
- ['globe', strings('misc.external.domain', {domain})]
- );
- return fixWS`${msg} `;
-}
-
-function generateChronologyLinks(currentThing, {
- contribKey,
- getThings,
- headingString,
- link,
- strings,
- wikiData
-}) {
- const { albumData } = wikiData;
-
- const contributions = currentThing[contribKey];
- if (!contributions) {
- return '';
- }
-
- if (contributions.length > 8) {
- return `${strings('misc.chronology.seeArtistPages')}
`;
- }
-
- return contributions.map(({ who: artist }) => {
- const things = sortByDate(unique(getThings(artist)));
- const releasedThings = things.filter(thing => {
- const album = albumData.includes(thing) ? thing : thing.album;
- return !(album && album.directory === UNRELEASED_TRACKS_DIRECTORY);
- });
- const index = releasedThings.indexOf(currentThing);
-
- if (index === -1) return '';
-
- // TODO: This can pro8a8ly 8e made to use generatePreviousNextLinks?
- // We'd need to make generatePreviousNextLinks use toAnythingMan tho.
- const previous = releasedThings[index - 1];
- const next = releasedThings[index + 1];
- const parts = [
- previous && linkAnythingMan(previous, {
- link, wikiData,
- color: false,
- text: strings('misc.nav.previous')
- }),
- next && linkAnythingMan(next, {
- link, wikiData,
- color: false,
- text: strings('misc.nav.next')
- })
- ].filter(Boolean);
-
- const stringOpts = {
- index: strings.count.index(index + 1, {strings}),
- artist: link.artist(artist)
- };
-
- return fixWS`
-
- ${strings(headingString, stringOpts)}
- ${parts.length && `(${parts.join(', ')}) `}
-
- `;
- }).filter(Boolean).join('\n');
-}
-
-function generateInfoGalleryLinks(currentThing, isGallery, {
- link, strings,
- linkKeyGallery,
- linkKeyInfo
-}) {
- return [
- link[linkKeyInfo](currentThing, {
- class: isGallery ? '' : 'current',
- text: strings('misc.nav.info')
- }),
- link[linkKeyGallery](currentThing, {
- class: isGallery ? 'current' : '',
- text: strings('misc.nav.gallery')
- })
- ].join(', ');
-}
-
-function generatePreviousNextLinks(current, {
- data,
- link,
- linkKey,
- strings
-}) {
- const linkFn = link[linkKey];
-
- const index = data.indexOf(current);
- const previous = data[index - 1];
- const next = data[index + 1];
-
- return [
- previous && linkFn(previous, {
- attributes: {
- id: 'previous-button',
- title: previous.name
- },
- text: strings('misc.nav.previous'),
- color: false
- }),
- next && linkFn(next, {
- attributes: {
- id: 'next-button',
- title: next.name
- },
- text: strings('misc.nav.next'),
- color: false
- })
- ].filter(Boolean).join(', ');
-}
-
// RIP toAnythingMan (previously getHrefOfAnythingMan), 2020-05-25<>2021-05-14.
// ........Yet the function 8reathes life anew as linkAnythingMan! ::::)
function linkAnythingMan(anythingMan, {link, wikiData, ...opts}) {
@@ -2412,11 +2102,6 @@ function linkAnythingMan(anythingMan, {link, wikiData, ...opts}) {
)
}
-function classes(...args) {
- const values = args.filter(Boolean);
- return `class="${values.join(' ')}"`;
-}
-
async function processLanguageFile(file, defaultStrings = null) {
let contents;
try {
@@ -3255,6 +2940,11 @@ async function main() {
bound.link = withEntries(unbound_link, entries => entries
.map(([ key, fn ]) => [key, bindOpts(fn, {to})]));
+ bound.linkAnythingMan = bindOpts(linkAnythingMan, {
+ link: bound.link,
+ wikiData
+ });
+
bound.parseAttributes = bindOpts(parseAttributes, {
to
});
@@ -3291,6 +2981,10 @@ async function main() {
strings
});
+ bound.getLinkThemeString = getLinkThemeString;
+
+ bound.getThemeString = getThemeString;
+
bound.getArtistString = bindOpts(getArtistString, {
iconifyURL: bound.iconifyURL,
link: bound.link,
@@ -3311,12 +3005,14 @@ async function main() {
bound.generateChronologyLinks = bindOpts(generateChronologyLinks, {
link: bound.link,
+ linkAnythingMan: bound.linkAnythingMan,
strings,
wikiData
});
bound.generateCoverLink = bindOpts(generateCoverLink, {
[bindOpts.bindIndex]: 0,
+ img,
link: bound.link,
strings,
to,
@@ -3336,6 +3032,8 @@ async function main() {
bound.getGridHTML = bindOpts(getGridHTML, {
[bindOpts.bindIndex]: 0,
+ getLinkThemeString,
+ img,
strings
});
@@ -3354,6 +3052,14 @@ async function main() {
to
});
+ bound.getRevealStringFromTags = bindOpts(getRevealStringFromTags, {
+ strings
+ });
+
+ bound.getRevealStringFromWarnings = bindOpts(getRevealStringFromWarnings, {
+ strings
+ });
+
bound.getAlbumStylesheet = bindOpts(getAlbumStylesheet, {
to
});
diff --git a/src/util/colors.js b/src/util/colors.js
index 01c55024..3a7ce8f3 100644
--- a/src/util/colors.js
+++ b/src/util/colors.js
@@ -19,31 +19,3 @@ export function getColors(primary) {
return {primary, dim, bg};
}
-
-export function getLinkThemeString(color) {
- if (!color) return '';
-
- const { primary, dim } = getColors(color);
- return `--primary-color: ${primary}; --dim-color: ${dim}`;
-}
-
-export function getThemeString(color, additionalVariables = []) {
- if (!color) return '';
-
- const { primary, dim, bg } = getColors(color);
-
- const variables = [
- `--primary-color: ${primary}`,
- `--dim-color: ${dim}`,
- `--bg-color: ${bg}`,
- ...additionalVariables
- ].filter(Boolean);
-
- if (!variables.length) return '';
-
- return (
- `:root {\n` +
- variables.map(line => ` ` + line + ';\n').join('') +
- `}`
- );
-}
diff --git a/src/util/link.js b/src/util/link.js
index 107b35ff..7ed5fd8e 100644
--- a/src/util/link.js
+++ b/src/util/link.js
@@ -10,7 +10,14 @@
// gener8ting just a8out any link on the site.
import * as html from './html.js'
-import { getLinkThemeString } from './colors.js'
+import { getColors } from './colors.js'
+
+export function getLinkThemeString(color) {
+ if (!color) return '';
+
+ const { primary, dim } = getColors(color);
+ return `--primary-color: ${primary}; --dim-color: ${dim}`;
+}
const linkHelper = (hrefFn, {color = true, attr = null} = {}) =>
(thing, {
--
cgit 1.3.0-6-gf8a5