« get me outta code hell

data, content, css: Aside Traack Section, Close Aside Track Section - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2026-07-07 21:18:03 -0300
committer(quasar) nebula <qznebula@protonmail.com>2026-07-07 21:18:03 -0300
commit2ccb0588a304b3ce8855651e8a30f895a57880c0 (patch)
treef878792b2c8dbb632f9acbd7ac1ed85aed25923d
parentb15da97e76176344d8b977558940a7f4324c0876 (diff)
data, content, css: Aside Traack Section, Close Aside Track Section preview
-rw-r--r--src/content/dependencies/generateAlbumTrackList.js56
-rw-r--r--src/content/dependencies/generateContentHeading.js1
-rw-r--r--src/data/files/album.js38
-rw-r--r--src/data/things/album/TrackSection.js14
-rw-r--r--src/data/things/album/index.js3
-rw-r--r--src/static/css/miscellany.css13
6 files changed, 109 insertions, 16 deletions
diff --git a/src/content/dependencies/generateAlbumTrackList.js b/src/content/dependencies/generateAlbumTrackList.js
index 6c8a21c2..7a30fa02 100644
--- a/src/content/dependencies/generateAlbumTrackList.js
+++ b/src/content/dependencies/generateAlbumTrackList.js
@@ -82,7 +82,14 @@ export default {
       case 'trackSections':
         data.trackSectionNames =
           album.trackSections
-            .map(section => section.name);
+            .map(section =>
+              (section.isDefaultTrackSection
+                ? null
+                : section.name));
+
+        data.trackSectionStyles =
+          album.trackSections
+            .map(section => section.style);
 
         data.trackSectionDurations =
           album.trackSections
@@ -138,6 +145,7 @@ export default {
             items: relations.trackSectionItems,
 
             name: data.trackSectionNames,
+            style: data.trackSectionStyles,
             duration: data.trackSectionDurations,
             durationApproximate: data.trackSectionDurationsApproximate,
             hasTrackNumbers: data.trackSectionsHaveTrackNumbers,
@@ -148,6 +156,7 @@ export default {
               items,
 
               name,
+              style,
               duration,
               durationApproximate,
               hasTrackNumbers,
@@ -157,37 +166,54 @@ export default {
                 heading.slots({
                   tag: 'dt',
 
+                  attributes: [
+                    style === 'aside' &&
+                      {class: 'aside'},
+                  ],
+
                   title:
-                    language.encapsulate(capsule, capsule => {
-                      const options = {section: name};
+                    language.encapsulate(capsule, workingCapsule => {
+                      const workingOptions = {
+                        [language.onlyIfOptions]: ['section'],
+                        section: name,
+                      };
+
+                      if (html.isBlank(name)) {
+                        return html.blank();
+                      }
 
                       if (duration) {
-                        capsule += '.withDuration';
-                        options.duration =
+                        workingCapsule += '.withDuration';
+                        workingOptions.duration =
                           language.formatDuration(duration, {
                             approximate: durationApproximate,
                           });
                       }
 
-                      return language.$(capsule, options);
+                      return language.$(workingCapsule, workingOptions);
                     }),
 
                   stickyTitle:
                     language.$(capsule, 'sticky', {
+                      [language.onlyIfOptions]: ['section'],
                       section: name,
                     }),
                 })),
 
-              html.tag('dd', [
-                html.tag('blockquote',
-                  {[html.onlyIfContent]: true},
-                  description),
+              html.tag('dd',
+                style === 'aside' &&
+                  {class: 'aside'},
+
+                [
+                  html.tag('blockquote',
+                    {[html.onlyIfContent]: true},
+                    description),
 
-                (hasTrackNumbers
-                  ? html.tag('ol', {start: startCountingFrom},
-                      slotItems(items))
-                  : html.tag('ul', slotItems(items))),
-              ]),
+                  (hasTrackNumbers
+                    ? html.tag('ol', {start: startCountingFrom},
+                        slotItems(items))
+                    : html.tag('ul', slotItems(items))),
+                ]),
             ]));
 
       case 'tracks':
diff --git a/src/content/dependencies/generateContentHeading.js b/src/content/dependencies/generateContentHeading.js
index a7cf201f..28e01b24 100644
--- a/src/content/dependencies/generateContentHeading.js
+++ b/src/content/dependencies/generateContentHeading.js
@@ -36,6 +36,7 @@ export default {
   generate: (relations, slots, {html}) =>
     html.tag(slots.tag, {class: 'content-heading'},
       {tabindex: '0'},
+      {[html.onlyIfContent]: true},
       {[html.onlyIfSiblings]: true},
 
       slots.attributes,
diff --git a/src/data/files/album.js b/src/data/files/album.js
index 84cda226..da687ddf 100644
--- a/src/data/files/album.js
+++ b/src/data/files/album.js
@@ -3,10 +3,18 @@ import * as path from 'node:path';
 import {traverse} from '#node-utils';
 import {sortAlbumsTracksChronologically, sortChronologically} from '#sort';
 import {empty} from '#sugar';
+import Thing from '#thing';
 
 export default ({
   documentModes: {headerAndEntries},
-  thingConstructors: {Album, Track, TrackSection},
+  thingConstructors: {
+    Album,
+    Track,
+    TrackSection,
+
+    AsideTrackSection,
+    CloseAsideTrackSection,
+  },
 }) => ({
   title: `Process album files`,
 
@@ -21,6 +29,10 @@ export default ({
   entryDocumentThing: document =>
     ('Section' in document
       ? TrackSection
+   : 'Aside Section' in document
+      ? AsideTrackSection
+   : 'Close Aside Section' in document
+      ? CloseAsideTrackSection
       : Track),
 
   connect({header: album, entries}) {
@@ -29,6 +41,8 @@ export default ({
     let currentTrackSection = new TrackSection();
     let currentTrackSectionTracks = [];
 
+    let latestNonAsideTrackSection = currentTrackSection;
+
     Object.assign(currentTrackSection, {
       name: `Default Track Section`,
       isDefaultTrackSection: true,
@@ -53,6 +67,28 @@ export default ({
         closeCurrentTrackSection();
         currentTrackSection = entry;
         currentTrackSectionTracks = [];
+
+        if (entry.style !== 'aside') {
+          latestNonAsideTrackSection = entry;
+        }
+
+        continue;
+      }
+
+      if (entry instanceof CloseAsideTrackSection) {
+        if (currentTrackSection.style !== 'aside') {
+          throw new Error(`Current track section "${currentTrackSection.name}" is not an aside`);
+        }
+
+        if (entry.name !== currentTrackSection.name) {
+          throw new Error(`Expected "Close Aside Section: ${currentTrackSection.name}", got "${entry.name}"`);
+        }
+
+        closeCurrentTrackSection();
+        currentTrackSection = Thing.clone(latestNonAsideTrackSection);
+        currentTrackSection.tracks = [];
+        currentTrackSectionTracks = [];
+
         continue;
       }
 
diff --git a/src/data/things/album/TrackSection.js b/src/data/things/album/TrackSection.js
index e579a0f6..86c754ac 100644
--- a/src/data/things/album/TrackSection.js
+++ b/src/data/things/album/TrackSection.js
@@ -50,6 +50,12 @@ export class TrackSection extends Thing {
 
     name: name(V('Unnamed Track Section')),
 
+    style: {
+      flags: {update: true, expose: true},
+      update: {validate: is('section', 'aside')},
+      expose: {transform: value => value ?? 'section'},
+    },
+
     // Track sections don't have a Name Detail themselves, but they do provide
     // a value which tracks can reference via 'Name Detail: section'.
     nameDetailForTracks: {
@@ -147,6 +153,14 @@ export class TrackSection extends Thing {
         validate: input.value(isBoolean),
       }),
 
+      {
+        dependencies: ['style'],
+        compute: (continuation, {style}) =>
+          (style === 'aside'
+            ? true
+            : continuation()),
+      },
+
       withPropertyFromObject('album', V('hideTrackSectionDurations')),
       exposeDependency('#album.hideTrackSectionDurations'),
     ],
diff --git a/src/data/things/album/index.js b/src/data/things/album/index.js
index 67bf47ab..a19144d9 100644
--- a/src/data/things/album/index.js
+++ b/src/data/things/album/index.js
@@ -1,2 +1,5 @@
 export * from './Album.js';
 export * from './TrackSection.js';
+
+export * from './AsideTrackSection.js';
+export * from './CloseAsideTrackSection.js';
diff --git a/src/static/css/miscellany.css b/src/static/css/miscellany.css
index 24eeba44..5cff2d57 100644
--- a/src/static/css/miscellany.css
+++ b/src/static/css/miscellany.css
@@ -582,6 +582,19 @@
     margin-left: 0;
   }
 
+  .album-group-list dt.aside {
+    margin-left: -5px;
+  }
+
+  .album-group-list dd.aside {
+    border-left: 1px dashed;
+    margin-left: 3px;
+  }
+
+  .album-group-list dd.aside :is(ul, ol) {
+    padding-left: 36px;
+  }
+
   .album-group-list li {
     padding-left: 1.5ch;
     text-indent: -1.5ch;