diff options
Diffstat (limited to 'src/content/dependencies/generatePageLayout.js')
-rw-r--r-- | src/content/dependencies/generatePageLayout.js | 278 |
1 files changed, 180 insertions, 98 deletions
diff --git a/src/content/dependencies/generatePageLayout.js b/src/content/dependencies/generatePageLayout.js index e138a981..070c7c82 100644 --- a/src/content/dependencies/generatePageLayout.js +++ b/src/content/dependencies/generatePageLayout.js @@ -1,10 +1,11 @@ import {openAggregate} from '#aggregate'; -import {empty} from '#sugar'; +import {atOffset, empty, repeat} from '#sugar'; export default { contentDependencies: [ 'generateColorStyleRules', 'generateFooterLocalizationLinks', + 'generateImageOverlay', 'generatePageSidebar', 'generateSearchSidebarBox', 'generateStickyHeadingContainer', @@ -16,25 +17,24 @@ export default { 'html', 'language', 'pagePath', + 'pagePathStringFromRoot', 'to', 'wikiData', ], - sprawl({wikiInfo}) { - return { - enableSearch: wikiInfo.enableSearch, - footerContent: wikiInfo.footerContent, - wikiColor: wikiInfo.color, - wikiName: wikiInfo.nameShort, - }; - }, + sprawl: ({wikiInfo}) => ({ + enableSearch: wikiInfo.enableSearch, + footerContent: wikiInfo.footerContent, + wikiColor: wikiInfo.color, + wikiName: wikiInfo.nameShort, + canonicalBase: wikiInfo.canonicalBase, + }), - data({wikiColor, wikiName}) { - return { - wikiColor, - wikiName, - }; - }, + data: (sprawl) => ({ + wikiColor: sprawl.wikiColor, + wikiName: sprawl.wikiName, + canonicalBase: sprawl.canonicalBase, + }), relations(relation, sprawl) { const relations = {}; @@ -61,6 +61,9 @@ export default { relations.colorStyleRules = relation('generateColorStyleRules'); + relations.imageOverlay = + relation('generateImageOverlay'); + return relations; }, @@ -71,8 +74,13 @@ export default { }, showWikiNameInTitle: { - type: 'boolean', - default: true, + validate: v => v.is(true, false, 'auto'), + default: 'auto', + }, + + subtitle: { + type: 'html', + mutable: false, }, showSearch: { @@ -85,7 +93,7 @@ export default { mutable: false, }, - cover: { + artworkColumnContent: { type: 'html', mutable: false, }, @@ -228,6 +236,7 @@ export default { html, language, pagePath, + pagePathStringFromRoot, to, }) { const colors = getColors(slots.color ?? data.wikiColor); @@ -241,6 +250,29 @@ export default { const mainContentHTML = html.tags([slots.mainContent]).toString(); const hasID = id => mainContentHTML.includes(`id="${id}"`); + const oEmbedJSONHref = + (hasSocialEmbed && data.canonicalBase + ? data.canonicalBase + + pagePathStringFromRoot + + 'oembed.json' + : null); + + const canonicalHref = + (data.canonicalBase + ? data.canonicalBase + pagePathStringFromRoot + : null); + + const firstItemInArtworkColumn = + html.smooth(slots.artworkColumnContent) + .content[0]; + + const primaryCover = + (firstItemInArtworkColumn && + html.resolve(firstItemInArtworkColumn, {normalize: 'tag'}) + .attributes.has('class', 'cover-artwork') + ? firstItemInArtworkColumn + : null); + const titleContentsHTML = (html.isBlank(slots.title) ? null @@ -255,12 +287,26 @@ export default { (html.isBlank(slots.title) ? null : slots.headingMode === 'sticky' - ? relations.stickyHeadingContainer.slots({ - title: titleContentsHTML, - cover: slots.cover, - }) + ? [ + relations.stickyHeadingContainer.slots({ + title: titleContentsHTML, + cover: primaryCover, + }), + + relations.stickyHeadingContainer.clone().slots({ + rootAttributes: {inert: true}, + }), + ] : html.tag('h1', titleContentsHTML)); + // TODO: There could be neat interactions with the sticky heading here, + // but for now subtitle is totally separate. + const subtitleHTML = + (html.isBlank(slots.subtitle) + ? null + : html.tag('h2', {class: 'page-subtitle'}, + language.sanitize(slots.subtitle))); + let footerContent = slots.footerContent; if (html.isBlank(footerContent) && relations.defaultFooterContent) { @@ -275,12 +321,19 @@ export default { html.tag('main', {id: 'content'}, {class: slots.mainClasses}, + !html.isBlank(subtitleHTML) && + {class: 'has-subtitle'}, + [ titleHTML, - html.tag('div', {id: 'cover-art-container'}, + html.tag('div', {id: 'artwork-column'}, {[html.onlyIfContent]: true}, - slots.cover), + {class: 'isolate-tooltip-z-indexing'}, + + slots.artworkColumnContent), + + subtitleHTML, slots.additionalNames, @@ -321,34 +374,32 @@ export default { slots.navLinks ?.filter(Boolean) - ?.map((cur, i) => { + ?.map((cur, i, entries) => { let content; if (cur.html) { content = cur.html; } else { + const attributes = html.attributes(); let title; - let href; switch (cur.auto) { case 'home': title = data.wikiName; - href = to('localized.home'); + attributes.set('href', to('localized.home')); break; case 'current': title = slots.title; - href = ''; + attributes.set('href', ''); break; case null: case undefined: title = cur.title; - href = to(...cur.path); + attributes.set('href', to(...cur.path)); break; } - content = html.tag('a', - {href}, - title); + content = html.tag('a', attributes, title); } const showAsCurrent = @@ -357,31 +408,51 @@ export default { (slots.navLinkStyle === 'hierarchical' && i === slots.navLinks.length - 1); - return ( + const navLink = html.tag('span', {class: 'nav-link'}, showAsCurrent && {class: 'current'}, [ html.tag('span', {class: 'nav-link-content'}, - // Use inline-block styling on the content span, - // rather than wrapping the whole nav-link in a proper - // blockwrap, so that if the content spans multiple - // lines, it'll kick the accent down beneath it. - i > 0 && - {class: 'blockwrap'}, - content), html.tag('span', {class: 'nav-link-accent'}, + {[html.noEdgeWhitespace]: true}, {[html.onlyIfContent]: true}, - cur.accent), - ])); + + language.$('misc.navAccent', { + [language.onlyIfOptions]: ['links'], + links: cur.accent, + })), + ]); + + if (slots.navLinkStyle === 'index') { + return navLink; + } + + const prev = + atOffset(entries, i, -1); + + if ( + prev && + prev.releaseRestToWrapTogether !== true && + (prev.releaseRestToWrapTogether === false || + prev.auto === 'home') + ) { + return navLink; + } else { + return html.metatag('blockwrap', navLink); + } })), html.tag('div', {class: 'nav-bottom-row'}, {[html.onlyIfContent]: true}, - slots.navBottomRowContent), + + language.$('misc.navAccent', { + [language.onlyIfOptions]: ['links'], + links: slots.navBottomRowContent, + })), html.tag('div', {class: 'nav-content'}, {[html.onlyIfContent]: true}, @@ -413,14 +484,15 @@ export default { let showingSidebarLeft; let showingSidebarRight; + let sidebarsInContentColumn = false; const leftSidebar = getSidebar('leftSidebar', 'sidebar-left', willShowSearch); const rightSidebar = getSidebar('rightSidebar', 'sidebar-right', false); if (willShowSearch) { if (html.isBlank(leftSidebar)) { - leftSidebar.setSlot('initiallyHidden', true); - showingSidebarLeft = false; + sidebarsInContentColumn = true; + showingSidebarLeft = true; } leftSidebar.setSlot( @@ -497,51 +569,31 @@ export default { {id: 'additional-files', string: 'additionalFiles'}, {id: 'commentary', string: 'commentary'}, {id: 'artist-commentary', string: 'artistCommentary'}, + {id: 'credit-sources', string: 'creditSources'}, ])), ]); - const imageOverlayHTML = html.tag('div', {id: 'image-overlay-container'}, - html.tag('div', {id: 'image-overlay-content-container'}, [ - html.tag('a', {id: 'image-overlay-image-container'}, [ - html.tag('img', {id: 'image-overlay-image'}), - html.tag('img', {id: 'image-overlay-image-thumb'}), - ]), - html.tag('div', {id: 'image-overlay-action-container'}, [ - html.tag('div', {id: 'image-overlay-action-content-without-size'}, - language.$('releaseInfo.viewOriginalFile', { - link: html.tag('a', {class: 'image-overlay-view-original'}, - language.$('releaseInfo.viewOriginalFile.link')), - })), + const styleRulesCSS = + html.resolve(slots.styleRules, {normalize: 'string'}); - html.tag('div', {id: 'image-overlay-action-content-with-size'}, [ - language.$('releaseInfo.viewOriginalFile.withSize', { - link: - html.tag('a', {class: 'image-overlay-view-original'}, - language.$('releaseInfo.viewOriginalFile.link')), - - size: - html.tag('span', - {[html.joinChildren]: ''}, - [ - html.tag('span', {id: 'image-overlay-file-size-kilobytes'}, - language.$('count.fileSize.kilobytes', { - kilobytes: - html.tag('span', {class: 'image-overlay-file-size-count'}), - })), - - html.tag('span', {id: 'image-overlay-file-size-megabytes'}, - language.$('count.fileSize.megabytes', { - megabytes: - html.tag('span', {class: 'image-overlay-file-size-count'}), - })), - ]), - }), + const fallbackBackgroundStyleRule = + (styleRulesCSS.match(/body::before[^}]*background-image:/) + ? '' + : `body::before {\n` + + ` background-image: url("${to('media.path', 'bg.jpg')}");\n` + + `}`); - html.tag('span', {id: 'image-overlay-file-size-warning'}, - language.$('releaseInfo.viewOriginalFile.sizeWarning')), - ]), - ]), - ])); + const numWallpaperParts = + html.resolve(slots.styleRules, {normalize: 'string'}) + .match(/\.wallpaper-part:nth-child/g) + ?.length ?? 0; + + const wallpaperPartsHTML = + html.tag('div', {class: 'wallpaper-parts'}, + {[html.onlyIfContent]: true}, + + repeat(numWallpaperParts, () => + html.tag('div', {class: 'wallpaper-part'}))); const layoutHTML = [ navHTML, @@ -587,14 +639,30 @@ export default { html.tag('head', [ html.tag('title', - (slots.showWikiNameInTitle - ? language.formatString('misc.pageTitle.withWikiName', { - title: slots.title, - wikiName: data.wikiName, - }) - : language.formatString('misc.pageTitle', { - title: slots.title, - }))), + language.encapsulate('misc.pageTitle', workingCapsule => { + const workingOptions = {}; + + workingOptions.title = slots.title; + + if (!html.isBlank(slots.subtitle)) { + workingCapsule += '.withSubtitle'; + workingOptions.subtitle = slots.subtitle; + } + + const showWikiName = + (slots.showWikiNameInTitle === true + ? true + : slots.showWikiNameInTitle === 'auto' + ? html.isBlank(slots.subtitle) + : false); + + if (showWikiName) { + workingCapsule += '.withWikiName'; + workingOptions.wikiName = data.wikiName; + } + + return language.$(workingCapsule, workingOptions); + })), html.tag('meta', {charset: 'utf-8'}), html.tag('meta', { @@ -626,13 +694,15 @@ export default { Object.entries(meta) .filter(([key, value]) => value) .map(([key, value]) => html.tag('meta', {[key]: value}))), + */ - canonical && + canonicalHref && html.tag('link', { rel: 'canonical', - href: canonical, + href: canonicalHref, }), + /* ...( localizedCanonical .map(({lang, href}) => html.tag('link', { @@ -640,7 +710,6 @@ export default { hreflang: lang, href, }))), - */ hasSocialEmbed && @@ -648,6 +717,12 @@ export default { .clone() .slot('mode', 'html'), + oEmbedJSONHref && + html.tag('link', { + type: 'application/json+oembed', + href: oEmbedJSONHref, + }), + html.tag('link', { rel: 'stylesheet', href: to('staticCSS.path', 'site.css'), @@ -656,6 +731,8 @@ export default { html.tag('style', [ relations.colorStyleRules .slot('color', slots.color ?? data.wikiColor), + + fallbackBackgroundStyleRule, slots.styleRules, ]), @@ -671,12 +748,14 @@ export default { html.tag('script', { blocking: 'render', type: 'module', - src: to('staticJS.path', 'client.js'), + src: to('staticJS.path', 'client/index.js'), }), ]), html.tag('body', [ + wallpaperPartsHTML, + html.tag('div', {id: 'page-container'}, showingSidebarLeft && {class: 'showing-sidebar-left'}, @@ -684,13 +763,16 @@ export default { showingSidebarRight && {class: 'showing-sidebar-right'}, + sidebarsInContentColumn && + {class: 'sidebars-in-content-column'}, + [ skippersHTML, layoutHTML, ]), // infoCardHTML, - imageOverlayHTML, + relations.imageOverlay, ]), ]) ]).toString(); |