« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/content/dependencies/generatePageLayout.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/content/dependencies/generatePageLayout.js')
-rw-r--r--src/content/dependencies/generatePageLayout.js168
1 files changed, 41 insertions, 127 deletions
diff --git a/src/content/dependencies/generatePageLayout.js b/src/content/dependencies/generatePageLayout.js
index 9e9b461..0bf3454 100644
--- a/src/content/dependencies/generatePageLayout.js
+++ b/src/content/dependencies/generatePageLayout.js
@@ -1,60 +1,6 @@
 import {openAggregate} from '#aggregate';
 import {empty} from '#sugar';
 
-function sidebarSlots(side) {
-  return {
-    // Content is a flat HTML array. It'll generate one sidebar section
-    // if specified.
-    [side + 'Content']: {
-      type: 'html',
-      mutable: false,
-    },
-
-    // A single class to apply to the whole sidebar. If specifying multiple
-    // sections, this be added to the containing sidebar-column - specify a
-    // class on each section if that's more suitable.
-    [side + 'Class']: {type: 'string'},
-
-    // Multiple is an array of objects, each specifying content (HTML) and
-    // optionally class (a string). Each of these will generate one sidebar
-    // section.
-    [side + 'Multiple']: {
-      validate: v =>
-        v.sparseArrayOf(
-          v.validateProperties({
-            class: v.optional(v.isString),
-            content: v.isHTML,
-          })),
-    },
-
-    // Sticky mode controls which sidebar section(s), if any, follow the
-    // scroll position, "sticking" to the top of the browser viewport.
-    //
-    // 'last' - last or only sidebar box is sticky
-    // 'column' - entire column, incl. multiple boxes from top, is sticky
-    // 'none' - sidebar not sticky at all, stays at top of page
-    //
-    // Note: This doesn't affect the content of any sidebar section, only
-    // the whole section's containing box (or the sidebar column as a whole).
-    [side + 'StickyMode']: {
-      validate: v => v.is('last', 'column', 'static'),
-      default: 'static',
-    },
-
-    // Collapsing sidebars disappear when the viewport is sufficiently
-    // thin. (This is the default.) Override as false to make the sidebar
-    // stay visible in thinner viewports, where the page layout will be
-    // reflowed so the sidebar is as wide as the screen and appears below
-    // nav, above the main content.
-    [side + 'Collapse']: {type: 'boolean', default: true},
-
-    // Wide sidebars generally take up more horizontal space in the normal
-    // page layout, and should be used if the content of the sidebar has
-    // a greater than typical focus compared to main content.
-    [side + 'Wide']: {type: 'boolean', defualt: false},
-  };
-}
-
 export default {
   contentDependencies: [
     'generateColorStyleRules',
@@ -162,8 +108,15 @@ export default {
 
     // Sidebars
 
-    ...sidebarSlots('leftSidebar'),
-    ...sidebarSlots('rightSidebar'),
+    leftSidebar: {
+      type: 'html',
+      mutable: true,
+    },
+
+    rightSidebar: {
+      type: 'html',
+      mutable: true,
+    },
 
     // Banner
 
@@ -266,6 +219,14 @@ export default {
     const colors = getColors(slots.color ?? data.wikiColor);
     const hasSocialEmbed = !html.isBlank(slots.socialEmbed);
 
+    // Hilariously jank. Sorry! We're going to need this content later ANYWAY,
+    // so it's "fine" to stringify it here, but this DOES mean that we're
+    // stringifying (and resolving) the content without the context that it's
+    // e.g. going to end up in a page HTML hierarchy. Might have implications
+    // later, mainly for: https://github.com/hsmusic/hsmusic-wiki/issues/434
+    const mainContentHTML = html.tags([slots.mainContent]).toString();
+    const hasID = id => mainContentHTML.includes(`id="${id}"`);
+
     const titleContentsHTML =
       (html.isBlank(slots.title)
         ? null
@@ -289,8 +250,11 @@ export default {
     let footerContent = slots.footerContent;
 
     if (html.isBlank(footerContent) && relations.defaultFooterContent) {
-      footerContent = relations.defaultFooterContent
-        .slot('mode', 'multiline');
+      footerContent =
+        relations.defaultFooterContent.slots({
+          mode: 'multiline',
+          indicateExternalLinks: false,
+        });
     }
 
     const mainHTML =
@@ -308,7 +272,7 @@ export default {
 
           html.tag('div', {class: 'main-content-container'},
             {[html.onlyIfContent]: true},
-            slots.mainContent),
+            mainContentHTML),
         ]);
 
     const footerHTML =
@@ -384,9 +348,6 @@ export default {
                     showAsCurrent &&
                       {class: 'current'},
 
-                    i > 0 &&
-                      {class: 'has-divider'},
-
                     [
                       html.tag('span', {class: 'nav-link-content'},
                         // Use inline-block styling on the content span,
@@ -413,64 +374,21 @@ export default {
             slots.navContent),
         ]);
 
-    const generateSidebarHTML = (side, id) => {
-      const content = slots[side + 'Content'];
-      const topClass = slots[side + 'Class'];
-      const multiple = slots[side + 'Multiple'];
-      const stickyMode = slots[side + 'StickyMode'];
-      const wide = slots[side + 'Wide'];
-      const collapse = slots[side + 'Collapse'];
-
-      let sidebarClasses = [];
-      let sidebarContent = html.blank();
-
-      if (!html.isBlank(content)) {
-        sidebarClasses = ['sidebar', topClass];
-        sidebarContent = content;
-      } else if (multiple) {
-        sidebarClasses = ['sidebar-multiple', topClass];
-        sidebarContent =
-          multiple
-            .filter(Boolean)
-            .map(box =>
-              html.tag('div', {class: 'sidebar'},
-                {[html.onlyIfContent]: true},
-                {class: box.class},
-                box.content));
-      }
-
-      if (html.isBlank(sidebarContent)) {
-        return html.blank();
-      }
-
-      return html.tag('div', {class: 'sidebar-column'},
-        {id, class: sidebarClasses},
-
-        wide &&
-          {class: 'wide'},
-
-        !collapse &&
-          {class: 'no-hide'},
-
-        stickyMode !== 'static' &&
-          {class: `sticky-${stickyMode}`},
-
-        sidebarContent);
-    }
-
-    const sidebarLeftHTML = generateSidebarHTML('leftSidebar', 'sidebar-left');
-    const sidebarRightHTML = generateSidebarHTML('rightSidebar', 'sidebar-right');
-
-    const hasSidebarLeft = !html.isBlank(sidebarLeftHTML);
-    const hasSidebarRight = !html.isBlank(sidebarRightHTML);
+    const getSidebar = (side, id) =>
+      (html.isBlank(slots[side])
+        ? html.blank()
+        : slots[side].slots({
+            attributes:
+              slots[side]
+                .getSlotValue('attributes')
+                .with({id}),
+          }));
 
-    const collapseSidebars = slots.leftSidebarCollapse && slots.rightSidebarCollapse;
+    const leftSidebar = getSidebar('leftSidebar', 'sidebar-left');
+    const rightSidebar = getSidebar('rightSidebar', 'sidebar-right');
 
-    const hasID = (() => {
-      // Hilariously jank. Sorry!
-      const mainContentHTML = slots.mainContent.toString();
-      return id => mainContentHTML.includes(`id="${id}"`);
-    })();
+    const hasSidebarLeft = !html.isBlank(html.resolve(leftSidebar));
+    const hasSidebarRight = !html.isBlank(html.resolve(rightSidebar));
 
     const processSkippers = skipperList =>
       skipperList
@@ -583,15 +501,11 @@ export default {
 
       slots.secondaryNav,
 
-      html.tag('div', {class: 'layout-columns'},
-        !collapseSidebars &&
-          {class: 'vertical-when-thin'},
-
-        [
-          sidebarLeftHTML,
-          mainHTML,
-          sidebarRightHTML,
-        ]),
+      html.tag('div', {class: 'layout-columns'}, [
+        leftSidebar,
+        mainHTML,
+        rightSidebar,
+      ]),
 
       slots.bannerPosition === 'bottom' &&
         slots.banner,