« get me outta code hell

Merge branch 'preview' into image-overlay - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-02-26 18:03:58 -0400
committer(quasar) nebula <qznebula@protonmail.com>2023-02-26 18:03:58 -0400
commit7bf9489f14735f9e44af37f2ade14890a119b403 (patch)
tree8b7742140ceeeda283edfe05f745d0e1a06050fe /src
parentae5f68ba51bbbe308cc56e70e70209652c869843 (diff)
parent8d05431f0c815227ba5cd503e88b0ee531c6eeb8 (diff)
Merge branch 'preview' into image-overlay
Diffstat (limited to 'src')
-rw-r--r--src/data/things/album.js2
-rw-r--r--src/data/things/track.js2
-rw-r--r--src/data/things/validators.js13
-rw-r--r--src/data/yaml.js73
-rw-r--r--src/util/html.js8
-rw-r--r--src/util/wiki-data.js41
-rw-r--r--src/write/build-modes/live-dev-server.js10
7 files changed, 63 insertions, 86 deletions
diff --git a/src/data/things/album.js b/src/data/things/album.js
index 0c0c7fb4..2a188f2d 100644
--- a/src/data/things/album.js
+++ b/src/data/things/album.js
@@ -106,7 +106,6 @@ export class Album extends Thing {
     hasCoverArt: Thing.common.flag(true),
     hasTrackArt: Thing.common.flag(true),
     hasTrackNumbers: Thing.common.flag(true),
-    isMajorRelease: Thing.common.flag(false),
     isListedOnHomepage: Thing.common.flag(true),
     isListedInGalleries: Thing.common.flag(true),
 
@@ -192,7 +191,6 @@ export class Album extends Thing {
     bannerDimensions: S.id,
 
     hasTrackArt: S.id,
-    isMajorRelease: S.id,
     isListedOnHomepage: S.id,
 
     commentary: S.id,
diff --git a/src/data/things/track.js b/src/data/things/track.js
index 6b1e958b..1778ed27 100644
--- a/src/data/things/track.js
+++ b/src/data/things/track.js
@@ -34,8 +34,6 @@ export class Track extends Thing {
     urls: Thing.common.urls(),
     dateFirstReleased: Thing.common.simpleDate(),
 
-    hasURLs: Thing.common.flag(true),
-
     artistContribsByRef: Thing.common.contribsByRef(),
     contributorContribsByRef: Thing.common.contribsByRef(),
     coverArtistContribsByRef: Thing.common.contribsByRef(),
diff --git a/src/data/things/validators.js b/src/data/things/validators.js
index 24db3c79..b116120a 100644
--- a/src/data/things/validators.js
+++ b/src/data/things/validators.js
@@ -195,7 +195,18 @@ export function isColor(color) {
 }
 
 export function isCommentary(commentary) {
-  return isString(commentary);
+  isString(commentary);
+
+  const [firstLine] = commentary.match(/.*/);
+  if (!firstLine.replace(/<\/b>/g, '').includes(':</i>')) {
+    throw new TypeError(`Missing commentary citation: "${
+      firstLine.length > 40
+        ? firstLine.slice(0, 40) + '...'
+        : firstLine
+    }"`);
+  }
+
+  return true;
 }
 
 const isArtistRef = validateReference('artist');
diff --git a/src/data/yaml.js b/src/data/yaml.js
index 9c3a4b88..6350588d 100644
--- a/src/data/yaml.js
+++ b/src/data/yaml.js
@@ -186,14 +186,20 @@ export const processAlbumDocument = makeProcessDocument(T.Album, {
 
   propertyFieldMapping: {
     name: 'Album',
-
-    color: 'Color',
     directory: 'Directory',
+    date: 'Date',
+    color: 'Color',
     urls: 'URLs',
 
-    artistContribsByRef: 'Artists',
-    coverArtistContribsByRef: 'Cover Artists',
-    trackCoverArtistContribsByRef: 'Default Track Cover Artists',
+    hasCoverArt: 'Has Cover Art',
+    hasTrackArt: 'Has Track Art',
+    hasTrackNumbers: 'Has Track Numbers',
+    isListedOnHomepage: 'Listed on Homepage',
+    isListedInGalleries: 'Listed in Galleries',
+
+    coverArtDate: 'Cover Art Date',
+    trackArtDate: 'Default Track Cover Art Date',
+    dateAddedToWiki: 'Date Added',
 
     coverArtFileExtension: 'Cover Art File Extension',
     trackCoverArtFileExtension: 'Track Art File Extension',
@@ -207,23 +213,14 @@ export const processAlbumDocument = makeProcessDocument(T.Album, {
     bannerFileExtension: 'Banner File Extension',
     bannerDimensions: 'Banner Dimensions',
 
-    date: 'Date',
-    trackArtDate: 'Default Track Cover Art Date',
-    coverArtDate: 'Cover Art Date',
-    dateAddedToWiki: 'Date Added',
-
-    hasCoverArt: 'Has Cover Art',
-    hasTrackArt: 'Has Track Art',
-    hasTrackNumbers: 'Has Track Numbers',
-    isMajorRelease: 'Major Release',
-    isListedOnHomepage: 'Listed on Homepage',
-    isListedInGalleries: 'Listed in Galleries',
+    commentary: 'Commentary',
+    additionalFiles: 'Additional Files',
 
+    artistContribsByRef: 'Artists',
+    coverArtistContribsByRef: 'Cover Artists',
+    trackCoverArtistContribsByRef: 'Default Track Cover Artists',
     groupsByRef: 'Groups',
     artTagsByRef: 'Art Tags',
-    commentary: 'Commentary',
-
-    additionalFiles: 'Additional Files',
   },
 });
 
@@ -255,44 +252,40 @@ export const processTrackDocument = makeProcessDocument(T.Track, {
 
   propertyFieldMapping: {
     name: 'Track',
-
     directory: 'Directory',
     duration: 'Duration',
     urls: 'URLs',
 
+    dateFirstReleased: 'Date First Released',
     coverArtDate: 'Cover Art Date',
     coverArtFileExtension: 'Cover Art File Extension',
-    dateFirstReleased: 'Date First Released',
     hasCoverArt: 'Has Cover Art',
-    hasURLs: 'Has URLs',
 
+    lyrics: 'Lyrics',
+    commentary: 'Commentary',
+    additionalFiles: 'Additional Files',
+
+    originalReleaseTrackByRef: 'Originally Released As',
     referencedTracksByRef: 'Referenced Tracks',
     sampledTracksByRef: 'Sampled Tracks',
     artistContribsByRef: 'Artists',
     contributorContribsByRef: 'Contributors',
     coverArtistContribsByRef: 'Cover Artists',
     artTagsByRef: 'Art Tags',
-    originalReleaseTrackByRef: 'Originally Released As',
-
-    commentary: 'Commentary',
-    lyrics: 'Lyrics',
-
-    additionalFiles: 'Additional Files',
   },
 });
 
 export const processArtistDocument = makeProcessDocument(T.Artist, {
   propertyFieldMapping: {
     name: 'Artist',
-
     directory: 'Directory',
     urls: 'URLs',
+    contextNotes: 'Context Notes',
+
     hasAvatar: 'Has Avatar',
     avatarFileExtension: 'Avatar File Extension',
 
     aliasNames: 'Aliases',
-
-    contextNotes: 'Context Notes',
   },
 
   ignoredFields: ['Dead URLs'],
@@ -307,15 +300,15 @@ export const processFlashDocument = makeProcessDocument(T.Flash, {
 
   propertyFieldMapping: {
     name: 'Flash',
-
     directory: 'Directory',
     page: 'Page',
+    urls: 'URLs',
+
     date: 'Date',
     coverArtFileExtension: 'Cover Art File Extension',
 
     featuredTracksByRef: 'Featured Tracks',
     contributorContribsByRef: 'Contributors',
-    urls: 'URLs',
   },
 });
 
@@ -375,8 +368,8 @@ export const processStaticPageDocument = makeProcessDocument(T.StaticPage, {
     nameShort: 'Short Name',
     directory: 'Directory',
 
-    content: 'Content',
     stylesheet: 'Style',
+    content: 'Content',
   },
 });
 
@@ -475,18 +468,6 @@ export function parseAdditionalFiles(array) {
   }));
 }
 
-export function parseCommentary(text) {
-  if (text) {
-    const lines = String(text.trim()).split('\n');
-    if (!lines[0].replace(/<\/b>/g, '').includes(':</i>')) {
-      throw new Error(`Missing commentary citation: "${lines[0].slice(0, 40)}..."`);
-    }
-    return text;
-  } else {
-    return null;
-  }
-}
-
 export function parseContributors(contributors) {
   // If this isn't something we can parse, just return it as-is.
   // The Thing object's validators will handle the data error better
diff --git a/src/util/html.js b/src/util/html.js
index a6b0d621..459a1647 100644
--- a/src/util/html.js
+++ b/src/util/html.js
@@ -130,6 +130,14 @@ export function attributes(attribs) {
         throw new Error(`Attribute value for ${key} should be primitive or array, got ${typeof val}`);
     })
     .filter(([_key, _val, keep]) => keep)
+    .map(([key, val]) => {
+      switch (key) {
+        case 'href':
+          return [key, encodeURI(val)];
+        default:
+          return [key, val];
+      }
+    })
     .map(([key, val]) =>
       typeof val === 'boolean'
         ? `${key}`
diff --git a/src/util/wiki-data.js b/src/util/wiki-data.js
index c93cb661..0eb86a1e 100644
--- a/src/util/wiki-data.js
+++ b/src/util/wiki-data.js
@@ -424,26 +424,14 @@ export function getArtistAvatar(artist, {to}) {
 // Big-ass homepage row functions
 
 export function getNewAdditions(numAlbums, {wikiData}) {
-  const {albumData} = wikiData;
-
-  // Sort al8ums, in descending order of priority, 8y...
-  //
-  // * D8te of addition to the wiki (descending).
-  // * Major releases first.
-  // * D8te of release (descending).
-  //
-  // Major releases go first to 8etter ensure they show up in the list (and
-  // are usually at the start of the final output for a given d8 of release
-  // too).
-  const sortedAlbums = albumData
+  const sortedAlbums = wikiData.albumData
     .filter((album) => album.isListedOnHomepage)
     .sort((a, b) => {
       if (a.dateAddedToWiki > b.dateAddedToWiki) return -1;
       if (a.dateAddedToWiki < b.dateAddedToWiki) return 1;
-      if (a.isMajorRelease && !b.isMajorRelease) return -1;
-      if (!a.isMajorRelease && b.isMajorRelease) return 1;
       if (a.date > b.date) return -1;
       if (a.date < b.date) return 1;
+      return 0;
     });
 
   // When multiple al8ums are added to the wiki at a time, we want to show
@@ -515,28 +503,13 @@ export function getNewAdditions(numAlbums, {wikiData}) {
     }
   }
 
-  // Finally, do some quick mapping shenanigans to 8etter display the result
-  // in a grid. (This should pro8a8ly 8e a separ8te, shared function, 8ut
-  // whatevs.)
-  return albums.map((album) => ({large: album.isMajorRelease, item: album}));
+  return albums.map((album) => ({item: album}));
 }
 
 export function getNewReleases(numReleases, {wikiData}) {
-  const {albumData} = wikiData;
-
-  const latestFirst = albumData
+  return wikiData.albumData
     .filter((album) => album.isListedOnHomepage)
-    .reverse();
-
-  const majorReleases = latestFirst.filter((album) => album.isMajorRelease);
-  majorReleases.splice(1);
-
-  const otherReleases = latestFirst
-    .filter((album) => !majorReleases.includes(album))
-    .slice(0, numReleases - majorReleases.length);
-
-  return [
-    ...majorReleases.map((album) => ({large: true, item: album})),
-    ...otherReleases.map((album) => ({large: false, item: album})),
-  ];
+    .reverse()
+    .slice(0, numReleases)
+    .map((album) => ({item: album}));
 }
diff --git a/src/write/build-modes/live-dev-server.js b/src/write/build-modes/live-dev-server.js
index 39229a9a..a8fd3705 100644
--- a/src/write/build-modes/live-dev-server.js
+++ b/src/write/build-modes/live-dev-server.js
@@ -163,7 +163,15 @@ export async function go({
         localDirectory = mediaPath;
       }
 
-      const filePath = path.resolve(localDirectory, safePath.split('/').join(path.sep));
+      let filePath;
+      try {
+        filePath = path.resolve(localDirectory, decodeURI(safePath.split('/').join(path.sep)));
+      } catch (error) {
+        response.writeHead(404, contentTypePlain);
+        response.end(`No ${localFileArea} file found for: ${safePath}`);
+        console.log(`${requestHead} [404] ${pathname}`);
+        console.log(`Failed to decode request pathname`);
+      }
 
       try {
         await stat(filePath);