From d756bee8ee4c8347930714998b43551a49330107 Mon Sep 17 00:00:00 2001 From: "(quasar) nebula" Date: Wed, 3 Apr 2024 11:56:32 -0300 Subject: content: generatePageSidebarBox, etc --- src/content/dependencies/generateAlbumSidebar.js | 98 ++++++++-------------- .../dependencies/generateAlbumSidebarGroupBox.js | 72 ++++++++-------- .../generateAlbumSidebarTrackListBox.js | 31 +++++++ src/content/dependencies/generatePageLayout.js | 26 +++--- src/content/dependencies/generatePageSidebar.js | 68 ++++++--------- src/content/dependencies/generatePageSidebarBox.js | 20 +++++ .../generatePageSidebarConjoinedBox.js | 42 ++++++++++ 7 files changed, 205 insertions(+), 152 deletions(-) create mode 100644 src/content/dependencies/generateAlbumSidebarTrackListBox.js create mode 100644 src/content/dependencies/generatePageSidebarBox.js create mode 100644 src/content/dependencies/generatePageSidebarConjoinedBox.js diff --git a/src/content/dependencies/generateAlbumSidebar.js b/src/content/dependencies/generateAlbumSidebar.js index 266a266..f014139 100644 --- a/src/content/dependencies/generateAlbumSidebar.js +++ b/src/content/dependencies/generateAlbumSidebar.js @@ -1,74 +1,46 @@ export default { contentDependencies: [ 'generateAlbumSidebarGroupBox', - 'generateAlbumSidebarTrackSection', + 'generateAlbumSidebarTrackListBox', 'generatePageSidebar', - 'linkAlbum', + 'generatePageSidebarConjoinedBox', ], - extraDependencies: ['html'], + relations: (relation, album, track) => ({ + sidebar: + relation('generatePageSidebar'), - relations(relation, album, track) { - const relations = {}; + conjoinedBox: + relation('generatePageSidebarConjoinedBox'), - relations.sidebar = - relation('generatePageSidebar'); + trackListBox: + relation('generateAlbumSidebarTrackListBox', album, track), - relations.albumLink = - relation('linkAlbum', album); - - relations.groupBoxes = + groupBoxes: album.groups.map(group => - relation('generateAlbumSidebarGroupBox', album, group)); - - relations.trackSections = - album.trackSections.map(trackSection => - relation('generateAlbumSidebarTrackSection', album, track, trackSection)); - - return relations; - }, - - data(album, track) { - return {isAlbumPage: !track}; - }, - - generate(data, relations, {html}) { - const multipleContents = []; - const multipleAttributes = []; - - multipleAttributes.push({class: 'track-list-sidebar-box'}); - multipleContents.push( - html.tags([ - html.tag('h1', relations.albumLink), - relations.trackSections, - ])); - - if (data.isAlbumPage) { - multipleAttributes.push(... - relations.groupBoxes - .map(() => ({class: 'individual-group-sidebar-box'}))); - - multipleContents.push(... - relations.groupBoxes - .map(content => content.slot('mode', 'album'))); - } else { - multipleAttributes.push({class: 'conjoined-group-sidebar-box'}); - multipleContents.push( - relations.groupBoxes - .flatMap((content, i, {length}) => [ - content.slot('mode', 'track'), - i < length - 1 && - html.tag('hr', { - style: `border-color: var(--primary-color); border-style: none none dotted none` - }), - ]) - .filter(Boolean)); - } - - return relations.sidebar.slots({ - // stickyMode: 'column', - multipleContents, - multipleAttributes, - }); - }, + relation('generateAlbumSidebarGroupBox', album, group)), + }), + + data: (album, track) => ({ + isAlbumPage: !track, + }), + + generate: (data, relations) => + relations.sidebar.slots({ + boxes: [ + relations.trackListBox, + + (data.isAlbumPage + ? relations.groupBoxes + .map(box => box.slot('mode', 'album')) + + : relations.conjoinedBox.slots({ + attributes: {class: 'conjoined-group-sidebar-box'}, + boxes: + relations.groupBoxes + .map(box => box.slot('mode', 'track')) + .map(box => box.content), /* TODO: Kludge. */ + })), + ], + }), }; diff --git a/src/content/dependencies/generateAlbumSidebarGroupBox.js b/src/content/dependencies/generateAlbumSidebarGroupBox.js index 93ebf5d..00a96c3 100644 --- a/src/content/dependencies/generateAlbumSidebarGroupBox.js +++ b/src/content/dependencies/generateAlbumSidebarGroupBox.js @@ -3,6 +3,7 @@ import {atOffset, empty} from '#sugar'; export default { contentDependencies: [ + 'generatePageSidebarBox', 'linkAlbum', 'linkExternal', 'linkGroup', @@ -40,6 +41,9 @@ export default { relations(relation, query, album, group) { const relations = {}; + relations.box = + relation('generatePageSidebarBox'); + relations.groupLink = relation('linkGroup', group); @@ -72,39 +76,41 @@ export default { }, }, - generate(relations, slots, {html, language}) { - return html.tags([ - html.tag('h1', - language.$('albumSidebar.groupBox.title', { - group: relations.groupLink, - })), - - slots.mode === 'album' && - relations.description - ?.slot('mode', 'multiline'), - - !empty(relations.externalLinks) && - html.tag('p', - language.$('releaseInfo.visitOn', { - links: - language.formatDisjunctionList( - relations.externalLinks - .map(link => link.slot('context', 'group'))), - })), - - slots.mode === 'album' && - relations.nextAlbumLink && - html.tag('p', {class: 'group-chronology-link'}, - language.$('albumSidebar.groupBox.next', { - album: relations.nextAlbumLink, + generate: (relations, slots, {html, language}) => + relations.box.slots({ + attributes: {class: 'individual-group-sidebar-box'}, + content: [ + html.tag('h1', + language.$('albumSidebar.groupBox.title', { + group: relations.groupLink, })), - slots.mode === 'album' && - relations.previousAlbumLink && - html.tag('p', {class: 'group-chronology-link'}, - language.$('albumSidebar.groupBox.previous', { - album: relations.previousAlbumLink, - })), - ]); - }, + slots.mode === 'album' && + relations.description + ?.slot('mode', 'multiline'), + + !empty(relations.externalLinks) && + html.tag('p', + language.$('releaseInfo.visitOn', { + links: + language.formatDisjunctionList( + relations.externalLinks + .map(link => link.slot('context', 'group'))), + })), + + slots.mode === 'album' && + relations.nextAlbumLink && + html.tag('p', {class: 'group-chronology-link'}, + language.$('albumSidebar.groupBox.next', { + album: relations.nextAlbumLink, + })), + + slots.mode === 'album' && + relations.previousAlbumLink && + html.tag('p', {class: 'group-chronology-link'}, + language.$('albumSidebar.groupBox.previous', { + album: relations.previousAlbumLink, + })), + ], + }), }; diff --git a/src/content/dependencies/generateAlbumSidebarTrackListBox.js b/src/content/dependencies/generateAlbumSidebarTrackListBox.js new file mode 100644 index 0000000..3a244e3 --- /dev/null +++ b/src/content/dependencies/generateAlbumSidebarTrackListBox.js @@ -0,0 +1,31 @@ +export default { + contentDependencies: [ + 'generateAlbumSidebarTrackSection', + 'generatePageSidebarBox', + 'linkAlbum', + ], + + extraDependencies: ['html'], + + relations: (relation, album, track) => ({ + box: + relation('generatePageSidebarBox'), + + albumLink: + relation('linkAlbum', album), + + trackSections: + album.trackSections.map(trackSection => + relation('generateAlbumSidebarTrackSection', album, track, trackSection)), + }), + + generate: (relations, {html}) => + relations.box.slots({ + attributes: {class: 'track-list-sidebar-box'}, + + content: [ + html.tag('h1', relations.albumLink), + relations.trackSections, + ], + }) +}; diff --git a/src/content/dependencies/generatePageLayout.js b/src/content/dependencies/generatePageLayout.js index 7fc6764..318c894 100644 --- a/src/content/dependencies/generatePageLayout.js +++ b/src/content/dependencies/generatePageLayout.js @@ -35,6 +35,7 @@ export default { 'generateColorStyleRules', 'generateFooterLocalizationLinks', 'generatePageSidebar', + 'generatePageSidebarBox', 'generateStickyHeadingContainer', 'transformContent', ], @@ -73,11 +74,11 @@ export default { relations.stickyHeadingContainer = relation('generateStickyHeadingContainer'); - relations.leftSidebar = + relations.sidebar = relation('generatePageSidebar'); - relations.rightSidebar = - relation('generatePageSidebar'); + relations.sidebarBox = + relation('generatePageSidebarBox'); if (sprawl.footerContent) { relations.defaultFooterContent = @@ -409,7 +410,7 @@ export default { ]); const applyLegacySidebarSlots = (side, id) => - relations[side].slots({ + relations.sidebar.clone().slots({ content: slots[side + 'Content'], attributes: [ @@ -418,16 +419,15 @@ export default { {class: slots[side + 'Class']}, ], - multipleContents: - (slots[side + 'Multiple'] - ? slots[side + 'Multiple'] - .map(({content}) => content) - : null), - - multipleAttributes: + boxes: (slots[side + 'Multiple'] - ? slots[side + 'Multiple'] - .map(({class: className}) => [{class: className}]) + ? slots[side + 'Multiple'].map(box => + relations.sidebarBox + .clone() + .slots({ + content: box.content, + attributes: {class: box.class}, + })) : null), stickyMode: slots[side + 'StickyMode'], diff --git a/src/content/dependencies/generatePageSidebar.js b/src/content/dependencies/generatePageSidebar.js index 1057627..a7da3d1 100644 --- a/src/content/dependencies/generatePageSidebar.js +++ b/src/content/dependencies/generatePageSidebar.js @@ -1,10 +1,14 @@ -import {empty, filterMultipleArrays, stitchArrays} from '#sugar'; - export default { + contentDependencies: ['generatePageSidebarBox'], extraDependencies: ['html'], + relations: (relation) => ({ + box: + relation('generatePageSidebarBox'), + }), + slots: { - // Content is a flat HTML array. It'll generate one sidebar section + // Content is a flat HTML array. It'll all be placed into one sidebar box // if specified. content: { type: 'html', @@ -19,14 +23,10 @@ export default { mutable: false, }, - // Chunks of content to be split into separate sections or "boxes" in the - // sidebar. Each of these can also be associated with HTML attributes. - multipleContents: { - validate: v => v.strictArrayOf(v.isHTML), - }, - - multipleAttributes: { - validate: v => v.strictArrayOf(v.isAttributes), + // Chunks of content to be split into separate boxes in the sidebar. + boxes: { + type: 'html', + mutable: false, }, // Sticky mode controls which sidebar sections, if any, follow the @@ -62,9 +62,12 @@ export default { }, }, - generate(slots, {html}) { + generate(relations, slots, {html}) { const attributes = - html.attributes({class: 'sidebar-column'}); + html.attributes({class: [ + 'sidebar-column', + 'sidebar-multiple', + ]}); attributes.add(slots.attributes); @@ -84,38 +87,17 @@ export default { attributes.add('class', `sticky-${slots.stickyMode}`); } - let content = slots.content; + const boxes = + (!html.isBlank(slots.boxes) + ? slots.boxes + : !html.isBlank(slots.content) + ? relations.box.slot('content', slots.content) + : html.blank()); - if (html.isBlank(content)) { - if (!slots.multipleContents) { - return html.blank(); - } - - const multipleContents = slots.multipleContents.slice(); - const multipleAttributes = slots.multipleAttributes?.slice() ?? []; - - filterMultipleArrays( - multipleContents, - multipleAttributes, - content => !html.isBlank(content)); - - if (empty(multipleContents)) { - return html.blank(); - } - - attributes.add('class', 'sidebar-multiple'); - content = - stitchArrays({ - content: multipleContents, - attributes: multipleAttributes, - }).map(({content, attributes}) => - html.tag('div', {class: 'sidebar'}, - attributes, - content)); + if (html.isBlank(boxes)) { + return html.blank(); } else { - attributes.add('class', 'sidebar'); + return html.tag('div', attributes, boxes); } - - return html.tag('div', attributes, content); }, }; diff --git a/src/content/dependencies/generatePageSidebarBox.js b/src/content/dependencies/generatePageSidebarBox.js new file mode 100644 index 0000000..5183545 --- /dev/null +++ b/src/content/dependencies/generatePageSidebarBox.js @@ -0,0 +1,20 @@ +export default { + extraDependencies: ['html'], + + slots: { + content: { + type: 'html', + mutable: false, + }, + + attributes: { + type: 'attributes', + mutable: false, + }, + }, + + generate: (slots, {html}) => + html.tag('div', {class: 'sidebar'}, + slots.attributes, + slots.content), +}; diff --git a/src/content/dependencies/generatePageSidebarConjoinedBox.js b/src/content/dependencies/generatePageSidebarConjoinedBox.js new file mode 100644 index 0000000..05b1d46 --- /dev/null +++ b/src/content/dependencies/generatePageSidebarConjoinedBox.js @@ -0,0 +1,42 @@ +// This component is kind of unfortunately magical. It reads the content of +// various boxes and joins them together, discarding the boxes' attributes. +// Since it requires access to the actual box *templates* (rather than those +// templates' resolved content), take care when slotting into this. + +export default { + contentDependencies: ['generatePageSidebarBox'], + extraDependencies: ['html'], + + relations: (relation) => ({ + box: + relation('generatePageSidebarBox'), + }), + + slots: { + attributes: { + type: 'attributes', + mutable: false, + }, + + boxes: { + validate: v => v.looseArrayOf(v.isTemplate), + }, + }, + + generate: (relations, slots, {html}) => + relations.box.slots({ + attributes: slots.attributes, + content: + slots.boxes.slice() + .map(box => box.getSlotValue('content')) + .map((content, index, {length}) => [ + content, + index < length - 1 && + html.tag('hr', { + style: + `border-color: var(--primary-color); ` + + `border-style: none none dotted none`, + }), + ]), + }), +}; -- cgit 1.3.0-6-gf8a5