« get me outta code hell

content: cut html.template boilerplate - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/content/dependencies/generateAdditionalFilesList.js
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-06-12 16:35:38 -0300
committer(quasar) nebula <qznebula@protonmail.com>2023-06-12 16:35:38 -0300
commit535acb34613b5cf7e22654619f4337b94b70644d (patch)
tree5a713eb4f12eae7e1fe1aa60941709708585db32 /src/content/dependencies/generateAdditionalFilesList.js
parent630af0a345f3be6c3e4aa3300ce138e48ed5ae91 (diff)
content: cut html.template boilerplate
Diffstat (limited to 'src/content/dependencies/generateAdditionalFilesList.js')
-rw-r--r--src/content/dependencies/generateAdditionalFilesList.js183
1 files changed, 83 insertions, 100 deletions
diff --git a/src/content/dependencies/generateAdditionalFilesList.js b/src/content/dependencies/generateAdditionalFilesList.js
index eb9fc8b..56e6686 100644
--- a/src/content/dependencies/generateAdditionalFilesList.js
+++ b/src/content/dependencies/generateAdditionalFilesList.js
@@ -1,5 +1,29 @@
 import {empty} from '../../util/sugar.js';
 
+function validateFileMapping(v, validateValue) {
+  return value => {
+    v.isObject(value);
+
+    const valueErrors = [];
+    for (const [fileKey, fileValue] of Object.entries(value)) {
+      if (fileValue === null) {
+        continue;
+      }
+
+      try {
+        validateValue(fileValue);
+      } catch (error) {
+        error.message = `(${fileKey}) ` + error.message;
+        valueErrors.push(error);
+      }
+    }
+
+    if (!empty(valueErrors)) {
+      throw new AggregateError(valueErrors, `Errors validating values`);
+    }
+  };
+}
+
 export default {
   extraDependencies: [
     'html',
@@ -14,108 +38,67 @@ export default {
     };
   },
 
-  generate(data, {
+  slots: {
+    fileLinks: {
+      validate: v => validateFileMapping(v, v.isHTML),
+    },
+
+    fileSizes: {
+      validate: v => validateFileMapping(v, v.isWholeNumber),
+    },
+  },
+
+  generate(data, slots, {
     html,
     language,
   }) {
-    const fileKeys = data.additionalFiles.flatMap(({files}) => files);
-    const validateFileMapping = (v, validateValue) => {
-      return value => {
-        v.isObject(value);
-
-        // It's OK to skip values for files, but if keys are provided for files
-        // which don't exist, that's an error.
-
-        const unexpectedKeys =
-          Object.keys(value).filter(key => !fileKeys.includes(key))
-
-        if (!empty(unexpectedKeys)) {
-          throw new TypeError(`Unexpected file keys: ${unexpectedKeys.join(', ')}`);
-        }
-
-        const valueErrors = [];
-        for (const [fileKey, fileValue] of Object.entries(value)) {
-          if (fileValue === null) {
-            continue;
-          }
-
-          try {
-            validateValue(fileValue);
-          } catch (error) {
-            error.message = `(${fileKey}) ` + error.message;
-            valueErrors.push(error);
-          }
-        }
-
-        if (!empty(valueErrors)) {
-          throw new AggregateError(valueErrors, `Errors validating values`);
-        }
-      };
-    };
-
-    return html.template({
-      annotation: 'generateAdditionalFilesList',
-
-      slots: {
-        fileLinks: {
-          validate: v => validateFileMapping(v, v.isHTML),
-        },
-
-        fileSizes: {
-          validate: v => validateFileMapping(v, v.isWholeNumber),
-        },
-      },
-
-      content(slots) {
-        if (!slots.fileSizes) {
-          return html.blank();
-        }
-
-        const filesWithLinks = new Set(
-          Object.entries(slots.fileLinks)
-            .filter(([key, value]) => value)
-            .map(([key]) => key));
-
-        if (filesWithLinks.size === 0) {
-          return html.blank();
-        }
-
-        const filteredFileGroups = data.additionalFiles
-          .map(({title, description, files}) => ({
-            title,
-            description,
-            files: files.filter(f => filesWithLinks.has(f)),
-          }))
-          .filter(({files}) => !empty(files));
-
-        if (empty(filteredFileGroups)) {
-          return html.blank();
-        }
-
-        return html.tag('dl',
-          filteredFileGroups.flatMap(({title, description, files}) => [
-            html.tag('dt',
-              (description
-                ? language.$('releaseInfo.additionalFiles.entry.withDescription', {
-                    title,
-                    description,
-                  })
-                : language.$('releaseInfo.additionalFiles.entry', {title}))),
-
-            html.tag('dd',
-              html.tag('ul',
-                files.map(file =>
-                  html.tag('li',
-                    (slots.fileSizes[file]
-                      ? language.$('releaseInfo.additionalFiles.file.withSize', {
-                          file: slots.fileLinks[file],
-                          size: language.formatFileSize(slots.fileSizes[file]),
-                        })
-                      : language.$('releaseInfo.additionalFiles.file', {
-                          file: slots.fileLinks[file],
-                        })))))),
-          ]));
-      },
-    });
+    if (!slots.fileSizes) {
+      return html.blank();
+    }
+
+    const filesWithLinks = new Set(
+      Object.entries(slots.fileLinks)
+        .filter(([key, value]) => value)
+        .map(([key]) => key));
+
+    if (filesWithLinks.size === 0) {
+      return html.blank();
+    }
+
+    const filteredFileGroups = data.additionalFiles
+      .map(({title, description, files}) => ({
+        title,
+        description,
+        files: files.filter(f => filesWithLinks.has(f)),
+      }))
+      .filter(({files}) => !empty(files));
+
+    if (empty(filteredFileGroups)) {
+      return html.blank();
+    }
+
+    return html.tag('dl',
+      filteredFileGroups.flatMap(({title, description, files}) => [
+        html.tag('dt',
+          (description
+            ? language.$('releaseInfo.additionalFiles.entry.withDescription', {
+                title,
+                description,
+              })
+            : language.$('releaseInfo.additionalFiles.entry', {title}))),
+
+        html.tag('dd',
+          html.tag('ul',
+            files.map(file =>
+              html.tag('li',
+                (slots.fileSizes[file]
+                  ? language.$('releaseInfo.additionalFiles.file.withSize', {
+                      file: slots.fileLinks[file],
+                      size: language.formatFileSize(slots.fileSizes[file]),
+                    })
+                  : language.$('releaseInfo.additionalFiles.file', {
+                      file: slots.fileLinks[file],
+                    })))))),
+      ]));
   },
 };