« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--site.css25
-rw-r--r--upd8-util.js12
-rw-r--r--upd8.js104
3 files changed, 98 insertions, 43 deletions
diff --git a/site.css b/site.css
index f10af38a..bd27d169 100644
--- a/site.css
+++ b/site.css
@@ -167,3 +167,28 @@ blockquote {
 p img {
     max-width: 100%;
 }
+
+dl dt {
+    padding-left: 2em;
+}
+
+dl dt {
+    margin-bottom: 2px;
+}
+
+dl dd {
+    margin-bottom: 1em;
+}
+
+dl {
+    counter-reset: subolcounter;
+}
+
+dl ol {
+    list-style: none;
+}
+
+dl ol li:before {
+    counter-increment: subolcounter;
+    content: counter(subolcounter) ". ";
+}
diff --git a/upd8-util.js b/upd8-util.js
index b94ffe3a..2fe2fcc8 100644
--- a/upd8-util.js
+++ b/upd8-util.js
@@ -57,3 +57,15 @@ module.exports.progressPromiseAll = function (msg, array) {
         return val;
     })));
 };
+
+module.exports.th = function (n) {
+    if (n % 10 === 1 && n !== 11) {
+        return n + 'st';
+    } else if (n % 10 === 2 && n !== 12) {
+        return n + 'nd';
+    } else if (n % 10 === 3 && n !== 13) {
+        return n + 'rd';
+    } else {
+        return n + 'th';
+    }
+};
diff --git a/upd8.js b/upd8.js
index c2aaad31..05df1f71 100644
--- a/upd8.js
+++ b/upd8.js
@@ -78,7 +78,8 @@ const access = util.promisify(fs.access);
 const {
     joinNoOxford,
     progressPromiseAll,
-    splitArray
+    splitArray,
+    th
 } = require('./upd8-util');
 
 const SITE_TITLE = 'Homestuck Music Wiki';
@@ -704,54 +705,43 @@ async function writeArtistPage(artistName, albumData) {
                     ].filter(Boolean).join(', ')}</p>
                     ${tracks.length && fixWS`
                         <h2 id="tracks">Tracks</h2>
-                        <ol>
-                            ${tracks.map(track => {
-                                const contrib = {
-                                    who: artistName,
-                                    what: [
-                                        ...track.contributors.filter(({ who }) => who === artistName).map(({ what }) => what),
-                                        ...getTracksReferencedBy(track, allTracks).filter(track => track.artists.includes(artistName)).map(track => `[${track.name}]`)
-                                    ].filter(Boolean).join(', ')
-                                };
-                                if (contrib.what && track.artists.includes(artistName)) {
-                                    const nonTracks = contrib.what.split(',').map(what => what.trim()).filter(what => !(what.startsWith('[') && what.endsWith(']')));
-                                    contrib.what = nonTracks.join(', ');
-                                }
-                                return fixWS`
-                                    <li class="${!track.artists.includes(artistName) && `contributed`}">
-                                        <a href="${TRACK_DIRECTORY}/${track.directory}/index.html">${track.name}</a>
-                                        ${track.artists.includes(artistName) && track.artists.length > 1 && `<span="contributed">(with ${getArtistString(track.artists.filter(a => a !== artistName))})</span>`}
-                                        ${contrib.what && `<span class="contributed">(${getContributionString(contrib, tracks) || 'contributed'})</span>`}
-                                        <i>from <a href="${ALBUM_DIRECTORY}/${track.album.directory}/index.html" style="${getThemeString(track.album.theme)}">${track.album.name}</a></i>
-                                    </li>
-                                `;
-                            }).join('\n')}
-                        </ol>
+                        ${albumChunkedList(tracks, (track, i) => {
+                            const contrib = {
+                                who: artistName,
+                                what: track.contributors.filter(({ who }) => who === artistName).map(({ what }) => what).join(', ')
+                            };
+                            return fixWS`
+                                <li title="${th(i + 1)} track by ${artistName}; ${th(track.album.tracks.indexOf(track) + 1)} in ${track.album.name}">
+                                    <a href="${TRACK_DIRECTORY}/${track.directory}/index.html" style="${getThemeString(track.album.theme)}">${track.name}</a>
+                                    ${track.artists.includes(artistName) && track.artists.length > 1 && `<span class="contributed">(with ${getArtistString(track.artists.filter(a => a !== artistName))})</span>`}
+                                    ${contrib.what && `<span class="contributed">(${getContributionString(contrib, tracks) || 'contributed'})</span>`}
+                                </li>
+                            `;
+                        })}
                     `}
                     ${artThings.length && fixWS`
                         <h2 id="art">Art</h2>
-                        <ol>
-                            ${artThings.map(thing => {
-                                const contrib = thing.coverArtists.find(({ who }) => who === artistName);
-                                return fixWS`
-                                    <li>
-                                        <a href="${thing.album ? TRACK_DIRECTORY : ALBUM_DIRECTORY}/${thing.directory}/index.html"${thing.theme && ` style="${getThemeString(thing.theme)}"`}>${thing.name}</a>
-                                        ${contrib.what && `<span class="contributed">(${getContributionString(contrib, tracks)})</span>`}
-                                        <i>${thing.album ? `from <a href="${ALBUM_DIRECTORY}/${thing.album.directory}/index.html" style="${getThemeString(thing.album.theme)}">${thing.album.name}</a>` : `(cover art)`}</i>
-                                    </li>
-                                `;
-                            }).join('\n')}
-                        </ol>
+                        ${albumChunkedList(artThings, (thing, i) => {
+                            const contrib = thing.coverArtists.find(({ who }) => who === artistName);
+                            return fixWS`
+                                <li title="${th(i + 1)} art by ${artistName}${thing.album && `; ${th(thing.album.tracks.indexOf(thing) + 1)} track in ${thing.album.name}`}">
+                                    ${thing.album ? fixWS`
+                                        <a href="${TRACK_DIRECTORY}/${thing.directory}/index.html" style="${getThemeString(thing.album.theme)}">${thing.name}</a>
+                                    ` : '<i>(cover art)</i>'}
+                                    ${contrib.what && `<span class="contributed">(${getContributionString(contrib, tracks)})</span>`}
+                                </li>
+                            `;
+                        })}
                     `}
                     ${commentaryThings.length && fixWS`
                         <h2 id="commentary">Commentary</h2>
-                        <ul>
-                            ${commentaryThings.map(thing => fixWS`
-                                <li>
-                                    <a href="${thing.album ? TRACK_DIRECTORY : ALBUM_DIRECTORY}/${thing.directory}/index.html"${thing.theme && ` style="${getThemeString(thing.theme)}"`}>${thing.name}</a>
-                                    <i>${thing.album ? `from <a href="${ALBUM_DIRECTORY}/${thing.album.directory}/index.html" style="${getThemeString(thing.album.theme)}">${thing.album.name}</a>` : `(album commentary)`}</i>
-                                </li>
-                            `).join('\n')}
+                        ${albumChunkedList(commentaryThings, thing => fixWS`
+                            <li>
+                                ${thing.album ? fixWS`
+                                    <a href="${TRACK_DIRECTORY}/${thing.directory}/index.html" style="${getThemeString(thing.album.theme)}">${thing.name}</a>
+                                ` : '(album commentary)'}
+                            </li>
+                        `, false)}
                         </ul>
                     `}
                 </div>
@@ -760,6 +750,34 @@ async function writeArtistPage(artistName, albumData) {
     `);
 }
 
+function albumChunkedList(tracks, getLI, showDate = true) {
+    const getAlbum = thing => thing.album ? thing.album : thing;
+    return fixWS`
+        <dl>
+            ${tracks.map((thing, i) => {
+                const li = getLI(thing, i);
+                const album = getAlbum(thing);
+                if (i === 0 || album !== getAlbum(tracks[i - 1]) || (showDate && +thing.date !== +tracks[i - 1].date)) {
+                    const heading = fixWS`
+                        <dt>
+                            <a href="${ALBUM_DIRECTORY}/${getAlbum(thing).directory}/index.html" style="${getThemeString(getAlbum(thing).theme)}">${getAlbum(thing).name}</a>
+                            ${showDate && `(${getDateString(thing)})`}
+                        </dt>
+                        <dd><ul>
+                    `;
+                    if (i > 0) {
+                        return ['</ul></dd>', heading, li];
+                    } else {
+                        return [heading, li];
+                    }
+                } else {
+                    return [li];
+                }
+            }).reduce((acc, arr) => acc.concat(arr), []).join('\n')}
+        </dl>
+    `;
+}
+
 // This function is terri8le. Sorry!
 function getContributionString({ what }, allTracks) {
     return what