diff options
7 files changed, 263 insertions, 111 deletions
diff --git a/src/content/dependencies/generateAlbumSecondaryNav.js b/src/content/dependencies/generateAlbumSecondaryNav.js index a5dc0ba8..ed43e51f 100644 --- a/src/content/dependencies/generateAlbumSecondaryNav.js +++ b/src/content/dependencies/generateAlbumSecondaryNav.js @@ -4,6 +4,7 @@ export default { contentDependencies: [ 'generateAlbumSecondaryNavGroupPart', 'generateAlbumSecondaryNavSeriesPart', + 'generateDotSwitcherTemplate', 'generateSecondaryNav', ], @@ -28,6 +29,12 @@ export default { secondaryNav: relation('generateSecondaryNav'), + // Just use a generic dot switcher here. We want the common behavior, + // but the "options" may each contain multiple links (group + series), + // so this is a different use than typical interpage dot switchers. + switcher: + relation('generateDotSwitcherTemplate'), + groupParts: query.groups .map(group => @@ -51,18 +58,37 @@ export default { }, }, - generate: (relations, slots) => - relations.secondaryNav.slots({ - class: 'nav-links-groups', + generate(relations, slots, {html}) { + const allParts = + stitchArrays({ + groupPart: relations.groupParts, + seriesParts: relations.seriesParts, + }).map(({groupPart, seriesParts}) => { + for (const part of [groupPart, ...seriesParts]) { + part.setSlot('mode', slots.mode); + } + + if (html.isBlank(seriesParts)) { + return groupPart; + } else { + return ( + html.tag('span', {class: 'group-with-series'}, + [groupPart, ...seriesParts])); + } + }); + + return relations.secondaryNav.slots({ + class: [ + 'album-secondary-nav', + + slots.mode === 'album' && + 'with-previous-next', + ], + content: - stitchArrays({ - groupPart: relations.groupParts, - seriesParts: relations.seriesParts, - }).map(({groupPart, seriesParts}) => [ - groupPart.slot('mode', slots.mode), - - seriesParts - .map(part => part.slot('mode', slots.mode)), - ]), - }), + (slots.mode === 'album' + ? allParts + : relations.switcher.slot('options', allParts)), + }); + }, }; diff --git a/src/content/dependencies/generateAlbumSecondaryNavGroupPart.js b/src/content/dependencies/generateAlbumSecondaryNavGroupPart.js index 81b0c75a..58a31630 100644 --- a/src/content/dependencies/generateAlbumSecondaryNavGroupPart.js +++ b/src/content/dependencies/generateAlbumSecondaryNavGroupPart.js @@ -4,12 +4,12 @@ import {atOffset} from '#sugar'; export default { contentDependencies: [ 'generateColorStyleAttribute', - 'generatePreviousNextLinks', + 'generateSecondaryNavParentSiblingsPart', 'linkAlbumDynamically', 'linkGroup', ], - extraDependencies: ['html', 'language'], + extraDependencies: ['html'], query(group, album) { const query = {}; @@ -38,15 +38,15 @@ export default { }, relations: (relation, query, group, _album) => ({ + parentSiblingsPart: + relation('generateSecondaryNavParentSiblingsPart'), + groupLink: relation('linkGroup', group), colorStyle: relation('generateColorStyleAttribute', group.color), - previousNextLinks: - relation('generatePreviousNextLinks'), - previousAlbumLink: (query.previousAlbum ? relation('linkAlbumDynamically', query.previousAlbum) @@ -65,34 +65,16 @@ export default { }, }, - generate: (relations, slots, {html, language}) => - html.tag('span', {class: 'nav-link'}, - relations.colorStyle - .slot('context', 'primary-only'), - - language.encapsulate('albumSecondaryNav.group', workingCapsule => { - const workingOptions = {}; - - workingOptions.group = - relations.groupLink - .slot('color', false); - - if (slots.mode === 'album') { - const {previousNextLinks} = relations; - - previousNextLinks.setSlots({ - previousLink: relations.previousAlbumLink, - nextLink: relations.nextAlbumLink, - id: false, - }); + generate: (relations, slots) => + relations.parentSiblingsPart.slots({ + mode: slots.mode, - if (!html.isBlank(previousNextLinks)) { - workingCapsule += '.withPreviousNext'; - workingOptions.previousNext = - language.formatUnitList(previousNextLinks.content); - } - } + colorStyle: relations.colorStyle, + mainLink: relations.groupLink, + previousLink: relations.previousAlbumLink, + nextLink: relations.nextAlbumLink, - return language.$(workingCapsule, workingOptions); - })), + stringsKey: 'albumSecondaryNav.group', + mainLinkOption: 'group', + }), }; diff --git a/src/content/dependencies/generateAlbumSecondaryNavSeriesPart.js b/src/content/dependencies/generateAlbumSecondaryNavSeriesPart.js index 47ba6ef6..12c72fd4 100644 --- a/src/content/dependencies/generateAlbumSecondaryNavSeriesPart.js +++ b/src/content/dependencies/generateAlbumSecondaryNavSeriesPart.js @@ -3,7 +3,7 @@ import {atOffset} from '#sugar'; export default { contentDependencies: [ 'generateColorStyleAttribute', - 'generatePreviousNextLinks', + 'generateSecondaryNavParentSiblingsPart', 'linkAlbumDynamically', 'linkGroup', ], @@ -29,15 +29,15 @@ export default { }, relations: (relation, query, series, _album) => ({ + parentSiblingsPart: + relation('generateSecondaryNavParentSiblingsPart'), + groupLink: relation('linkGroup', series.group), colorStyle: relation('generateColorStyleAttribute', series.group.color), - previousNextLinks: - relation('generatePreviousNextLinks'), - previousAlbumLink: (query.previousAlbum ? relation('linkAlbumDynamically', query.previousAlbum) @@ -60,40 +60,24 @@ export default { }, }, - generate: (data, relations, slots, {html, language}) => - html.tag('span', - {class: 'nav-link'}, - {class: 'series-nav-link'}, - - relations.colorStyle - .slot('context', 'primary-only'), - - language.encapsulate('albumSecondaryNav.series', workingCapsule => { - const workingOptions = {}; - - workingOptions.series = - relations.groupLink.slots({ - attributes: {class: 'series'}, - color: false, - content: language.sanitize(data.name), - }); - - if (slots.mode === 'album') { - const {previousNextLinks} = relations; - - previousNextLinks.setSlots({ - previousLink: relations.previousAlbumLink, - nextLink: relations.nextAlbumLink, - id: false, - }); - - if (!html.isBlank(previousNextLinks)) { - workingCapsule += '.withPreviousNext'; - workingOptions.previousNext = - language.formatUnitList(previousNextLinks.content); - } - } - - return language.$(workingCapsule, workingOptions); - })), + generate: (data, relations, slots, {language}) => + relations.parentSiblingsPart.slots({ + mode: slots.mode, + + attributes: {class: 'series-nav-link'}, + + colorStyle: relations.colorStyle, + + mainLink: + relations.groupLink.slots({ + attributes: {class: 'series'}, + content: language.sanitize(data.name), + }), + + previousLink: relations.previousAlbumLink, + nextLink: relations.nextAlbumLink, + + stringsKey: 'albumSecondaryNav.series', + mainLinkOption: 'series', + }), }; diff --git a/src/content/dependencies/generateSecondaryNavParentSiblingsPart.js b/src/content/dependencies/generateSecondaryNavParentSiblingsPart.js new file mode 100644 index 00000000..c5f1df84 --- /dev/null +++ b/src/content/dependencies/generateSecondaryNavParentSiblingsPart.js @@ -0,0 +1,103 @@ +export default { + contentDependencies: [ + 'generateColorStyleAttribute', + 'generateInterpageDotSwitcher', + 'generateNextLink', + 'generatePreviousLink', + 'linkAlbumDynamically', + 'linkGroup', + ], + + extraDependencies: ['html', 'language'], + + relations: (relation) => ({ + switcher: + relation('generateInterpageDotSwitcher'), + + previousLink: + relation('generatePreviousLink'), + + nextLink: + relation('generateNextLink'), + }), + + slots: { + mode: { + validate: v => v.is('album', 'track'), + default: 'album', + }, + + attributes: { + type: 'attributes', + mutable: false, + }, + + colorStyle: { + type: 'html', + mutable: true, + }, + + mainLink: { + type: 'html', + mutable: true, + }, + + previousLink: { + type: 'html', + mutable: false, + }, + + nextLink: { + type: 'html', + mutable: false, + }, + + stringsKey: { + type: 'string', + }, + + mainLinkOption: { + type: 'string', + }, + }, + + generate: (relations, slots, {html, language}) => + html.tag('span', + slots.attributes, + + !html.isBlank(slots.colorStyle) && + slots.colorStyle + .slot('context', 'primary-only'), + + language.encapsulate(slots.stringsKey, workingCapsule => { + const workingOptions = {}; + + workingOptions[slots.mainLinkOption] = + slots.mainLink + .slot('color', false); + + if (slots.mode === 'album') addPreviousNext: { + if (html.isBlank(slots.previousLink) && html.isBlank(slots.nextLink)) { + break addPreviousNext; + } + + workingCapsule += '.withPreviousNext'; + workingOptions.previousNext = + relations.switcher.slots({ + links: [ + relations.previousLink.slots({ + id: false, + link: slots.previousLink, + }), + + relations.nextLink.slots({ + id: false, + link: slots.nextLink, + }), + ], + }); + } + + return language.$(workingCapsule, workingOptions); + })), +}; diff --git a/src/static/css/site.css b/src/static/css/site.css index a46c0927..081c184b 100644 --- a/src/static/css/site.css +++ b/src/static/css/site.css @@ -842,7 +842,7 @@ a:not([href]):hover { content: "\0020/\0020"; } -.nav-links-groups .series-nav-link:not(:first-child)::before { +.series-nav-link:not(:first-child)::before { content: "\0020»\0020"; font-weight: normal; } @@ -868,6 +868,33 @@ a:not([href]):hover { #secondary-nav { text-align: center; + + /* Default to visible. It'll automatically be hidden + * in layouts where the sidebar is visible. + */ + display: block; +} + +#secondary-nav.album-secondary-nav.with-previous-next { + display: flex; + justify-content: space-around; + padding-left: 15% !important; + padding-right: 15% !important; + flex-wrap: wrap; + line-height: 1.4; +} + +#secondary-nav.album-secondary-nav.with-previous-next .group-with-series { + width: 100%; +} + +#secondary-nav.album-secondary-nav.with-previous-next > * { + margin-left: 5px; + margin-right: 5px; +} + +#secondary-nav.album-secondary-nav .dot-switcher { + white-space: nowrap; } .inert-previous-next-link { @@ -2942,10 +2969,6 @@ html[data-language-code="preview-en"][data-url-key="localized.home"] #content display: none; } - #secondary-nav { - display: block; - } - .layout-columns { flex-direction: column; } diff --git a/tap-snapshots/test/snapshot/generateAlbumSecondaryNav.js.test.cjs b/tap-snapshots/test/snapshot/generateAlbumSecondaryNav.js.test.cjs index de35048c..145dd0f7 100644 --- a/tap-snapshots/test/snapshot/generateAlbumSecondaryNav.js.test.cjs +++ b/tap-snapshots/test/snapshot/generateAlbumSecondaryNav.js.test.cjs @@ -6,28 +6,29 @@ */ 'use strict' exports[`test/snapshot/generateAlbumSecondaryNav.js > TAP > generateAlbumSecondaryNav (snapshot) > basic behavior, mode: album 1`] = ` -<nav id="secondary-nav" class="nav-links-groups"> - <span class="nav-link" style="--primary-color: #abcdef"> - <a href="group/vcg/">VCG</a> - (<a title="First" href="album/first/">Previous</a>, <a title="Last" href="album/last/">Next</a>) - </span> - <span class="nav-link" style="--primary-color: #123456"> - <a href="group/bepis/">Bepis</a> - (<a title="Second" href="album/second/">Next</a>) +<nav id="secondary-nav" class="album-secondary-nav with-previous-next"> + <span class="group-with-series"> + <span style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a> (<span class="dot-switcher interpage"><span><a title="First" href="album/first/">Previous</a></span><span><a title="Last" href="album/last/">Next</a></span></span>)</span> + <span class="series-nav-link" style="--primary-color: #abcdef"><a class="series" href="group/vcg/">Series</a> (<span class="dot-switcher interpage"><span><a class="inert-previous-next-link">Previous</a></span><span><a title="Last" href="album/last/">Next</a></span></span>)</span> </span> + <span style="--primary-color: #123456"><a href="group/bepis/">Bepis</a> (<span class="dot-switcher interpage"><span><a class="inert-previous-next-link">Previous</a></span><span><a title="Second" href="album/second/">Next</a></span></span>)</span> </nav> ` exports[`test/snapshot/generateAlbumSecondaryNav.js > TAP > generateAlbumSecondaryNav (snapshot) > basic behavior, mode: track 1`] = ` -<nav id="secondary-nav" class="nav-links-groups"> - <span class="nav-link" style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a></span> - <span class="nav-link" style="--primary-color: #123456"><a href="group/bepis/">Bepis</a></span> +<nav id="secondary-nav" class="album-secondary-nav"> + <span class="dot-switcher"><span> + <span class="group-with-series"> + <span style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a></span> + <span class="series-nav-link" style="--primary-color: #abcdef"><a class="series" href="group/vcg/">Series</a></span> + </span> + </span><span><span style="--primary-color: #123456"><a href="group/bepis/">Bepis</a></span></span></span> </nav> ` exports[`test/snapshot/generateAlbumSecondaryNav.js > TAP > generateAlbumSecondaryNav (snapshot) > dateless album in mixed group 1`] = ` -<nav id="secondary-nav" class="nav-links-groups"> - <span class="nav-link" style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a></span> - <span class="nav-link" style="--primary-color: #123456"><a href="group/bepis/">Bepis</a></span> +<nav id="secondary-nav" class="album-secondary-nav with-previous-next"> + <span style="--primary-color: #abcdef"><a href="group/vcg/">VCG</a></span> + <span style="--primary-color: #123456"><a href="group/bepis/">Bepis</a></span> </nav> ` diff --git a/test/snapshot/generateAlbumSecondaryNav.js b/test/snapshot/generateAlbumSecondaryNav.js index 57618f2f..2495bc4a 100644 --- a/test/snapshot/generateAlbumSecondaryNav.js +++ b/test/snapshot/generateAlbumSecondaryNav.js @@ -4,10 +4,21 @@ import {testContentFunctions} from '#test-lib'; testContentFunctions(t, 'generateAlbumSecondaryNav (snapshot)', async (t, evaluate) => { await evaluate.load(); - let album, group1, group2; + let album, anotherAlbum, group1, group2; - group1 = {name: 'VCG', directory: 'vcg', color: '#abcdef'}; - group2 = {name: 'Bepis', directory: 'bepis', color: '#123456'}; + group1 = { + name: 'VCG', + directory: 'vcg', + color: '#abcdef', + serieses: [], + }; + + group2 = { + name: 'Bepis', + directory: 'bepis', + color: '#123456', + serieses: [], + }; album = { name: 'Album', @@ -16,15 +27,37 @@ testContentFunctions(t, 'generateAlbumSecondaryNav (snapshot)', async (t, evalua groups: [group1, group2], }; + anotherAlbum = { + name: 'Last', + directory: 'last', + date: new Date('2010-06-12'), + }; + group1.albums = [ - {name: 'First', directory: 'first', date: new Date('2010-04-10')}, + { + name: 'First', + directory: 'first', + date: new Date('2010-04-10'), + }, album, - {name: 'Last', directory: 'last', date: new Date('2010-06-12')}, + anotherAlbum, + ]; + + group1.serieses = [ + { + name: 'Series', + albums: [album, anotherAlbum], + group: group1, + }, ]; group2.albums = [ album, - {name: 'Second', directory: 'second', date: new Date('2011-04-13')}, + { + name: 'Second', + directory: 'second', + date: new Date('2011-04-13'), + }, ]; evaluate.snapshot('basic behavior, mode: album', { |