« 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
diff options
context:
space:
mode:
Diffstat (limited to 'src/content')
-rw-r--r--src/content/dependencies/generateAlbumCoverArtwork.js23
-rw-r--r--src/content/dependencies/generateFlashCoverArtwork.js12
-rw-r--r--src/content/dependencies/generateFlashInfoPage.js148
-rw-r--r--src/content/dependencies/generateFlashNavAccent.js79
-rw-r--r--src/content/dependencies/generateTrackCoverArtwork.js27
-rw-r--r--src/content/dependencies/linkExternal.js39
6 files changed, 282 insertions, 46 deletions
diff --git a/src/content/dependencies/generateAlbumCoverArtwork.js b/src/content/dependencies/generateAlbumCoverArtwork.js
index f7e86303..cbec930e 100644
--- a/src/content/dependencies/generateAlbumCoverArtwork.js
+++ b/src/content/dependencies/generateAlbumCoverArtwork.js
@@ -1,23 +1,12 @@
 export default {
   contentDependencies: ['generateCoverArtwork'],
 
-  relations(relation, album) {
-    return {
-      coverArtwork:
-        relation('generateCoverArtwork', album.artTags),
-    };
-  },
+  relations: (relation, album) =>
+    ({coverArtwork: relation('generateCoverArtwork', album.artTags)}),
 
-  data(album) {
-    return {
-      path: ['media.albumCover', album.directory, album.coverArtFileExtension],
-    };
-  },
+  data: (album) =>
+    ({path: ['media.albumCover', album.directory, album.coverArtFileExtension]}),
 
-  generate(data, relations) {
-    return relations.coverArtwork
-      .slots({
-        path: data.path,
-      });
-  },
+  generate: (data, relations) =>
+    relations.coverArtwork.slot('path', data.path),
 };
diff --git a/src/content/dependencies/generateFlashCoverArtwork.js b/src/content/dependencies/generateFlashCoverArtwork.js
new file mode 100644
index 00000000..374fa3f8
--- /dev/null
+++ b/src/content/dependencies/generateFlashCoverArtwork.js
@@ -0,0 +1,12 @@
+export default {
+  contentDependencies: ['generateCoverArtwork'],
+
+  relations: (relation) =>
+    ({coverArtwork: relation('generateCoverArtwork')}),
+
+  data: (flash) =>
+    ({path: ['media.flashArt', flash.directory, flash.coverArtFileExtension]}),
+
+  generate: (data, relations) =>
+    relations.coverArtwork.slot('path', data.path),
+};
diff --git a/src/content/dependencies/generateFlashInfoPage.js b/src/content/dependencies/generateFlashInfoPage.js
index 4316d7c1..af92ddff 100644
--- a/src/content/dependencies/generateFlashInfoPage.js
+++ b/src/content/dependencies/generateFlashInfoPage.js
@@ -1,38 +1,172 @@
+import {empty} from '../../util/sugar.js';
+
 export default {
-  contentDependencies: ['generatePageLayout'],
+  contentDependencies: [
+    'generateContentHeading',
+    'generateContributionList',
+    'generateFlashCoverArtwork',
+    'generateFlashNavAccent',
+    'generatePageLayout',
+    'generateTrackList',
+    'linkExternal',
+    'linkFlashIndex',
+  ],
+
   extraDependencies: ['html', 'language'],
 
-  relations(relation) {
+  query(flash) {
+    const query = {};
+
+    if (flash.page || !empty(flash.urls)) {
+      query.urls = [];
+
+      if (flash.page) {
+        query.urls.push(`https://homestuck.com/story/${flash.page}`);
+      }
+
+      if (!empty(flash.urls)) {
+        query.urls.push(...flash.urls);
+      }
+    }
+
+    return query;
+  },
+
+  relations(relation, query, flash) {
     const relations = {};
+    const sections = relations.sections = {};
 
     relations.layout =
       relation('generatePageLayout');
 
+    if (query.urls) {
+      relations.externalLinks =
+        query.urls.map(url => relation('linkExternal', url));
+    }
+
+    // TODO: Flashes always have cover art (#175)
+    /* eslint-disable-next-line no-constant-condition */
+    if (true) {
+      relations.cover =
+        relation('generateFlashCoverArtwork', flash);
+    }
+
+    // Section: navigation bar
+
+    const nav = sections.nav = {};
+
+    nav.flashIndexLink =
+      relation('linkFlashIndex');
+
+    nav.flashNavAccent =
+      relation('generateFlashNavAccent', flash);
+
+    // Section: Featured tracks
+
+    if (!empty(flash.featuredTracks)) {
+      const featuredTracks = sections.featuredTracks = {};
+
+      featuredTracks.heading =
+        relation('generateContentHeading');
+
+      featuredTracks.list =
+        relation('generateTrackList', flash.featuredTracks);
+    }
+
+    // Section: Contributors
+
+    if (!empty(flash.contributorContribs)) {
+      const contributors = sections.contributors = {};
+
+      contributors.heading =
+        relation('generateContentHeading');
+
+      contributors.list =
+        relation('generateContributionList', flash.contributorContribs);
+    }
+
     return relations;
   },
 
-  data(flash) {
-    return {
-      name: flash.name,
-    };
+  data(query, flash) {
+    const data = {};
+
+    data.name = flash.name;
+    data.color = flash.color;
+    data.date = flash.date;
+
+    return data;
   },
 
   generate(data, relations, {html, language}) {
+    const {sections: sec} = relations;
+
     return relations.layout.slots({
       title:
         language.$('flashPage.title', {
           flash: data.name,
         }),
 
+      color: data.color,
+      headingMode: 'sticky',
+
+      cover:
+        (relations.cover
+          ? relations.cover.slots({
+              alt: language.$('misc.alt.flashArt'),
+            })
+          : null),
+
       mainContent: [
-        html.tag('p', `Alright alright, this is a stub page! Coming soon!`),
+        html.tag('p',
+          language.$('releaseInfo.released', {
+            date: language.formatDate(data.date),
+          })),
+
+        relations.externalLinks &&
+          html.tag('p',
+            language.$('releaseInfo.playOn', {
+              links:
+                language.formatDisjunctionList(
+                  relations.externalLinks
+                    .map(link => link.slot('mode', 'flash'))),
+            })),
+
+        sec.featuredTracks && [
+          sec.featuredTracks.heading
+            .slots({
+              id: 'features',
+              title:
+                language.$('releaseInfo.tracksFeatured', {
+                  flash: html.tag('i', data.name),
+                }),
+            }),
+
+          sec.featuredTracks.list,
+        ],
+
+        sec.contributors && [
+          sec.contributors.heading
+            .slots({
+              id: 'contributors',
+              title: language.$('releaseInfo.contributors'),
+            }),
+
+          sec.contributors.list,
+        ],
       ],
 
       navLinkStyle: 'hierarchical',
       navLinks: [
         {auto: 'home'},
+        {html: sec.nav.flashIndexLink},
         {auto: 'current'},
       ],
+
+      navBottomRowContent:
+        sec.nav.flashNavAccent.slots({
+          showFlashNavigation: true,
+        }),
     });
   },
 };
diff --git a/src/content/dependencies/generateFlashNavAccent.js b/src/content/dependencies/generateFlashNavAccent.js
new file mode 100644
index 00000000..1e2d1852
--- /dev/null
+++ b/src/content/dependencies/generateFlashNavAccent.js
@@ -0,0 +1,79 @@
+import {empty} from '../../util/sugar.js';
+import {sortFlashesChronologically} from '../../util/wiki-data.js';
+
+export default {
+  contentDependencies: [
+    'generatePreviousNextLinks',
+    'linkFlash',
+  ],
+
+  extraDependencies: ['html', 'language', 'wikiData'],
+
+  sprawl({flashData}) {
+    return {flashData};
+  },
+
+  query(sprawl, flash) {
+    const flashes =
+      sortFlashesChronologically(sprawl.flashData.slice());
+
+    const index = flashes.indexOf(flash);
+
+    const previousFlash =
+      (index > 0
+        ? flashes[index - 1]
+        : null);
+
+    const nextFlash =
+      (index < flashes.length - 1
+        ? flashes[index + 1]
+        : null);
+
+    return {previousFlash, nextFlash};
+  },
+
+  relations(relation, query) {
+    const relations = {};
+
+    if (query.previousFlash || query.nextFlash) {
+      relations.previousNextLinks =
+        relation('generatePreviousNextLinks');
+
+      relations.previousFlashLink =
+        (query.previousFlash
+          ? relation('linkFlash', query.previousFlash)
+          : null);
+
+      relations.nextFlashLink =
+        (query.nextFlash
+          ? relation('linkFlash', query.nextFlash)
+          : null);
+    }
+
+    return relations;
+  },
+
+  slots: {
+    showFlashNavigation: {type: 'boolean', default: false},
+  },
+
+  generate(relations, slots, {html, language}) {
+    const {content: previousNextLinks = []} =
+      slots.showFlashNavigation &&
+      relations.previousNextLinks &&
+        relations.previousNextLinks.slots({
+          previousLink: relations.previousFlashLink,
+          nextLink: relations.nextFlashLink,
+        });
+
+    const allLinks = [
+      ...previousNextLinks,
+    ].filter(Boolean);
+
+    if (empty(allLinks)) {
+      return html.blank();
+    }
+
+    return `(${language.formatUnitList(allLinks)})`;
+  },
+};
diff --git a/src/content/dependencies/generateTrackCoverArtwork.js b/src/content/dependencies/generateTrackCoverArtwork.js
index 757ad2d6..ec0488e2 100644
--- a/src/content/dependencies/generateTrackCoverArtwork.js
+++ b/src/content/dependencies/generateTrackCoverArtwork.js
@@ -1,29 +1,20 @@
 export default {
   contentDependencies: ['generateCoverArtwork'],
 
-  relations(relation, track) {
-    return {
-      coverArtwork:
+  relations: (relation, track) =>
+    ({coverArtwork:
         relation('generateCoverArtwork',
           (track.hasUniqueCoverArt
             ? track.artTags
-            : track.album.artTags)),
-    };
-  },
+            : track.album.artTags))}),
 
-  data(track) {
-    return {
-      path:
+  data: (track) =>
+    ({path:
         (track.hasUniqueCoverArt
           ? ['media.trackCover', track.album.directory, track.directory, track.coverArtFileExtension]
-          : ['media.albumCover', track.album.directory, track.album.coverArtFileExtension]),
-    };
-  },
+          : ['media.albumCover', track.album.directory, track.album.coverArtFileExtension])}),
 
-  generate(data, relations) {
-    return relations.coverArtwork
-      .slots({
-        path: data.path,
-      });
-  },
+  generate: (data, relations) =>
+    relations.coverArtwork.slot('path', data.path),
 };
+
diff --git a/src/content/dependencies/linkExternal.js b/src/content/dependencies/linkExternal.js
index 7c3d86a8..73c656e3 100644
--- a/src/content/dependencies/linkExternal.js
+++ b/src/content/dependencies/linkExternal.js
@@ -11,7 +11,7 @@ export default {
 
   slots: {
     mode: {
-      validate: v => v.is('generic', 'album'),
+      validate: v => v.is('generic', 'album', 'flash'),
       default: 'generic',
     },
   },
@@ -19,15 +19,18 @@ export default {
   generate(data, slots, {html, language}) {
     let isLocal;
     let domain;
+    let pathname;
     try {
-      domain = new URL(data.url).hostname;
+      const url = new URL(data.url);
+      domain = url.hostname;
+      pathname = url.pathname;
     } catch (error) {
       // No support for relative local URLs yet, sorry! (I.e, local URLs must
       // be absolute relative to the domain name in order to work.)
       isLocal = true;
     }
 
-    const a = html.tag('a',
+    const link = html.tag('a',
       {
         href: data.url,
         class: 'nowrap',
@@ -85,6 +88,34 @@ export default {
 
         : domain);
 
-    return a;
+    switch (slots.mode) {
+      case 'flash': {
+        const wrap = content =>
+          html.tag('span', {class: 'nowrap'}, content);
+
+        if (domain.includes('homestuck.com')) {
+          const match = pathname.match(/\/story\/(.*)\/?/);
+          if (match) {
+            if (isNaN(Number(match[1]))) {
+              return wrap(language.$('misc.external.flash.homestuck.secret', {link}));
+            } else {
+              return wrap(language.$('misc.external.flash.homestuck.page', {
+                link,
+                page: match[1],
+              }));
+            }
+          }
+        } else if (domain.includes('bgreco.net')) {
+          return wrap(language.$('misc.external.flash.bgreco', {link}));
+        } else if (domain.includes('youtu')) {
+          return wrap(language.$('misc.external.flash.youtube', {link}));
+        }
+
+        return link;
+      }
+
+      default:
+        return link;
+    }
   }
 };