« 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--src/content/dependencies/generateCommentaryIndexPage.js102
-rw-r--r--src/content/dependencies/transformContent.js16
-rw-r--r--src/page/album.js18
-rw-r--r--src/page/artist-alias.js2
-rw-r--r--src/page/group.js20
-rw-r--r--src/static/site4.css5
-rwxr-xr-xsrc/upd8.js2
-rw-r--r--src/url-spec.js1
-rw-r--r--src/write/build-modes/live-dev-server.js6
-rw-r--r--src/write/build-modes/static-build.js76
10 files changed, 192 insertions, 56 deletions
diff --git a/src/content/dependencies/generateCommentaryIndexPage.js b/src/content/dependencies/generateCommentaryIndexPage.js
new file mode 100644
index 0000000..0cb5a40
--- /dev/null
+++ b/src/content/dependencies/generateCommentaryIndexPage.js
@@ -0,0 +1,102 @@
+import {accumulateSum, stitchArrays} from '../../util/sugar.js';
+import {filterMultipleArrays, sortChronologically} from '../../util/wiki-data.js';
+
+export default {
+  contentDependencies: ['generatePageLayout', 'linkAlbumCommentary'],
+  extraDependencies: ['html', 'language', 'wikiData'],
+
+  sprawl({albumData}) {
+    return {albumData};
+  },
+
+  query(sprawl) {
+    const query = {};
+
+    query.albums =
+      sortChronologically(sprawl.albumData.slice());
+
+    const entries =
+      query.albums.map(album =>
+        [album, ...album.tracks]
+          .filter(({commentary}) => commentary)
+          .map(({commentary}) => commentary));
+
+    query.wordCounts =
+      entries.map(entries =>
+        accumulateSum(
+          entries,
+          entry => entry.split(' ').length));
+
+    query.entryCounts =
+      entries.map(entries => entries.length);
+
+    filterMultipleArrays(query.albums, query.wordCounts, query.entryCounts,
+      (album, wordCount, entryCount) => entryCount >= 1);
+
+    return query;
+  },
+
+  relations(relation, query) {
+    return {
+      layout:
+        relation('generatePageLayout'),
+
+      albumLinks:
+        query.albums
+          .map(album => relation('linkAlbumCommentary', album)),
+    };
+  },
+
+  data(query) {
+    return {
+      wordCounts: query.wordCounts,
+      entryCounts: query.entryCounts,
+
+      totalWordCount: accumulateSum(query.wordCounts),
+      totalEntryCount: accumulateSum(query.entryCounts),
+    };
+  },
+
+  generate(data, relations, {html, language}) {
+    return relations.layout.slots({
+      title: language.$('commentaryIndex.title'),
+
+      headingMode: 'static',
+
+      mainClasses: ['long-content'],
+      mainContent: [
+        html.tag('p', language.$('commentaryIndex.infoLine', {
+          words:
+            html.tag('b',
+              language.formatWordCount(data.totalWordCount, {unit: true})),
+
+          entries:
+            html.tag('b',
+                language.countCommentaryEntries(data.totalEntryCount, {unit: true})),
+        })),
+
+        html.tag('p',
+          language.$('commentaryIndex.albumList.title')),
+
+        html.tag('ul',
+          stitchArrays({
+            albumLink: relations.albumLinks,
+            wordCount: data.wordCounts,
+            entryCount: data.entryCounts,
+          }).map(({albumLink, wordCount, entryCount}) =>
+            html.tag('li',
+              language.$('commentaryIndex.albumList.item', {
+                album: albumLink,
+                words: language.formatWordCount(wordCount, {unit: true}),
+                entries: language.countCommentaryEntries(entryCount, {unit: true}),
+              })))),
+      ],
+
+      navLinkStyle: 'hierarchical',
+      navLinks: [
+        {auto: 'home'},
+        {auto: 'current'},
+      ],
+    });
+  },
+};
diff --git a/src/content/dependencies/transformContent.js b/src/content/dependencies/transformContent.js
index 848727d..a194e26 100644
--- a/src/content/dependencies/transformContent.js
+++ b/src/content/dependencies/transformContent.js
@@ -359,14 +359,14 @@ export default {
             return {
               type: 'image',
               data:
-                image.slots({
-                  src,
-                  class: 'content-image',
-                  link: link ?? true,
-                  width: width ?? null,
-                  height: height ?? null,
-                  thumb: slots.thumb,
-                }),
+                html.tag('div', {class: 'content-image'},
+                  image.slots({
+                    src,
+                    link: link ?? true,
+                    width: width ?? null,
+                    height: height ?? null,
+                    thumb: slots.thumb,
+                  })),
             };
           }
 
diff --git a/src/page/album.js b/src/page/album.js
index a8e0b59..3b2d02d 100644
--- a/src/page/album.js
+++ b/src/page/album.js
@@ -55,6 +55,24 @@ export function pathsForTarget(album) {
   ];
 }
 
+export function pathsTargetless({wikiData: {wikiInfo}}) {
+  return [
+    {
+      type: 'page',
+      path: ['commentaryIndex'],
+      contentFunction: {name: 'generateCommentaryIndexPage'},
+    },
+
+    wikiInfo.canonicalBase === 'https://hsmusic.wiki/' &&
+      {
+        type: 'redirect',
+        fromPath: ['page', 'list/all-commentary'],
+        toPath: ['commentaryIndex'],
+        title: 'Album Commentary',
+      },
+  ];
+}
+
 /*
 export function write(album, {wikiData}) {
   const getSocialEmbedDescription = ({
diff --git a/src/page/artist-alias.js b/src/page/artist-alias.js
index 9e9fdf5..23513ce 100644
--- a/src/page/artist-alias.js
+++ b/src/page/artist-alias.js
@@ -15,7 +15,7 @@ export function pathsForTarget(aliasArtist) {
       type: 'redirect',
       fromPath: ['artist', aliasArtist.directory],
       toPath: ['artist', aliasedArtist.directory],
-      title: () => aliasedArtist.name,
+      title: aliasedArtist.name,
     },
   ];
 }
diff --git a/src/page/group.js b/src/page/group.js
index 4d5f91c..fa6c1c9 100644
--- a/src/page/group.js
+++ b/src/page/group.js
@@ -40,3 +40,23 @@ export function pathsForTarget(group) {
     },
   ];
 }
+
+export function pathsTargetless({wikiData: {wikiInfo}}) {
+  return [
+    wikiInfo.canonicalBase === 'https://hsmusic.wiki/' &&
+      {
+        type: 'redirect',
+        fromPath: ['page', 'albums/fandom'],
+        toPath: ['groupGallery', 'fandom'],
+        title: 'Fandom - Gallery',
+      },
+
+    wikiInfo.canonicalBase === 'https://hsmusic.wiki/' &&
+      {
+        type: 'redirect',
+        fromPath: ['page', 'albums/official'],
+        toPath: ['groupGallery', 'official'],
+        title: 'Official - Gallery',
+      },
+  ];
+}
diff --git a/src/static/site4.css b/src/static/site4.css
index c9843bc..dd6f104 100644
--- a/src/static/site4.css
+++ b/src/static/site4.css
@@ -539,8 +539,7 @@ p .current {
   display: none;
 }
 
-a.box.content-image {
-  display: block;
+.content-image {
   margin-top: 1em;
   margin-bottom: 1em;
 }
@@ -559,7 +558,7 @@ a.box img {
   height: auto;
 }
 
-a.box .image-container.placeholder-image {
+a.box .square .image-container {
   width: 100%;
   height: 100%;
 }
diff --git a/src/upd8.js b/src/upd8.js
index 11ede7b..fabda27 100755
--- a/src/upd8.js
+++ b/src/upd8.js
@@ -174,7 +174,7 @@ async function main() {
     // 8uild with the default (English) strings if this path is left
     // unspecified.
     'lang-path': {
-      help: `Specify path to language directory, including JSON files that mapping internal string keys to localized language content, and various language metadata`,
+      help: `Specify path to language directory, including JSON files that mapping internal string keys to localized language content, and various language metadata\n\nOptional for wiki building, unless the wiki's default language is not English; may be provided via the HSMUSIC_LANG environment variable instead`,
       type: 'value',
     },
 
diff --git a/src/url-spec.js b/src/url-spec.js
index d1e347e..8340f19 100644
--- a/src/url-spec.js
+++ b/src/url-spec.js
@@ -21,6 +21,7 @@ const urlSpec = {
     paths: {
       root: '',
       path: '<>',
+      page: '<>/',
 
       home: '',
 
diff --git a/src/write/build-modes/live-dev-server.js b/src/write/build-modes/live-dev-server.js
index a87da27..edee326 100644
--- a/src/write/build-modes/live-dev-server.js
+++ b/src/write/build-modes/live-dev-server.js
@@ -321,6 +321,10 @@ export async function go({
 
     try {
       if (page.type === 'redirect') {
+        const title =
+          page.title ??
+          page.getTitle?.({language});
+
         const target = to('localized.' + page.toPath[0], ...page.toPath.slice(1));
 
         response.writeHead(301, {
@@ -328,7 +332,7 @@ export async function go({
           'Location': target,
         });
 
-        const redirectHTML = generateRedirectHTML(page.title, target, {language});
+        const redirectHTML = generateRedirectHTML(title, target, {language});
 
         response.end(redirectHTML);
 
diff --git a/src/write/build-modes/static-build.js b/src/write/build-modes/static-build.js
index bf722bf..4f07405 100644
--- a/src/write/build-modes/static-build.js
+++ b/src/write/build-modes/static-build.js
@@ -78,6 +78,36 @@ export function getCLIOptions() {
   };
 }
 
+function generateRedirectHTML(title, target, {language}) {
+  return `<!DOCTYPE html>\n` + html.tag('html', [
+    html.tag('head', [
+      html.tag('title', language.$('redirectPage.title', {title})),
+      html.tag('meta', {charset: 'utf-8'}),
+
+      html.tag('meta', {
+        'http-equiv': 'refresh',
+        content: `0;url=${target}`,
+      }),
+
+      // TODO: Is this OK for localized pages?
+      html.tag('link', {
+        rel: 'canonical',
+        href: target,
+      }),
+    ]),
+
+    html.tag('body',
+      html.tag('main', [
+        html.tag('h1',
+          language.$('redirectPage.title', {title})),
+        html.tag('p',
+          language.$('redirectPage.infoLine', {
+            target: html.tag('a', {href: target}, target),
+          })),
+      ])),
+  ]);
+}
+
 export async function go({
   cliOptions,
   _dataPath,
@@ -124,6 +154,8 @@ export async function go({
   const writeAll = empty(selectedPageFlags) || selectedPageFlags.includes('all');
   logInfo`Writing site pages: ${writeAll ? 'all' : selectedPageFlags.join(', ')}`;
 
+  await mkdir(outputPath, {recursive: true});
+
   await writeSymlinks({
     srcRootPath,
     mediaPath,
@@ -323,11 +355,8 @@ export async function go({
         });
       }),
 
-      /*
-      ...redirectWrites.map(({fromPath, toPath, title: titleFn}) => () => {
-        const title = titleFn({
-          language,
-        });
+      ...redirectWrites.map(({fromPath, toPath, title, getTitle}) => () => {
+        title ??= getTitle?.({language});
 
         const to = getURLsFrom({
           baseDirectory,
@@ -348,7 +377,6 @@ export async function go({
           })),
         });
       }),
-      */
     ], queueSize));
   };
 
@@ -473,45 +501,9 @@ async function writeSharedFilesAndPages({
   const {groupData, wikiInfo} = wikiData;
 
   return progressPromiseAll(`Writing files & pages shared across languages.`, [
-    /*
-    groupData?.some((group) => group.directory === 'fandom') &&
-      redirect(
-        'Fandom - Gallery',
-        'albums/fandom',
-        'localized.groupGallery',
-        'fandom'
-      ),
-
-    groupData?.some((group) => group.directory === 'official') &&
-      redirect(
-        'Official - Gallery',
-        'albums/official',
-        'localized.groupGallery',
-        'official'
-      ),
-
-    wikiInfo.enableListings &&
-      redirect(
-        'Album Commentary',
-        'list/all-commentary',
-        'localized.commentaryIndex',
-        ''
-      ),
-    */
-
     wikiDataJSON &&
       writeFile(
         path.join(outputPath, 'data.json'),
         wikiDataJSON),
   ].filter(Boolean));
-
-  async function redirect(title, from, urlKey, directory) {
-    const target = path.relative(
-      from,
-      urls.from('shared.root').to(urlKey, directory)
-    );
-    const content = generateRedirectHTML(title, target, {language});
-    await mkdir(path.join(outputPath, from), {recursive: true});
-    await writeFile(path.join(outputPath, from, 'index.html'), content);
-  }
 }