« get me outta code hell

infra: automatically interface html.stationery via slots - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2023-06-12 14:51:45 -0300
committer(quasar) nebula <qznebula@protonmail.com>2023-06-12 14:51:45 -0300
commit1fe5de18a35a51b251c08995e619a5a526425236 (patch)
tree221e0233ba6f6b6e9649d3880024a88abc034e29
parentf12890facba502805f03a64c76f386c4531abbcc (diff)
infra: automatically interface html.stationery via slots
-rw-r--r--src/content-function.js49
1 files changed, 45 insertions, 4 deletions
diff --git a/src/content-function.js b/src/content-function.js
index 3f9d658a..d4cc3dbc 100644
--- a/src/content-function.js
+++ b/src/content-function.js
@@ -8,6 +8,7 @@ export default function contentFunction({
   contentDependencies = [],
   extraDependencies = [],
 
+  slots,
   sprawl,
   relations,
   data,
@@ -35,11 +36,16 @@ export default function contentFunction({
     throw new Error(`Content functions which sprawl must specify wikiData in extraDependencies`);
   }
 
+  if (slots && !expectedExtraDependencyKeys.has('html')) {
+    throw new Error(`Content functions with slots must specify html in extraDependencies`);
+  }
+
   // Pass all the details to expectDependencies, which will recursively build
   // up a set of fulfilled dependencies and make functions like `relations`
   // and `generate` callable only with sufficient fulfilled dependencies.
 
   return expectDependencies({
+    slots,
     sprawl,
     relations,
     data,
@@ -58,6 +64,7 @@ export default function contentFunction({
 contentFunction.identifyingSymbol = Symbol(`Is a content function?`);
 
 export function expectDependencies({
+  slots,
   sprawl,
   relations,
   data,
@@ -74,6 +81,7 @@ export function expectDependencies({
   const hasSprawlFunction = !!sprawl;
   const hasRelationsFunction = !!relations;
   const hasDataFunction = !!data;
+  const hasSlotsDescription = !!slots;
 
   const isInvalidated = !empty(invalidatingDependencyKeys);
   const isMissingContentDependencies = !empty(missingContentDependencyKeys);
@@ -96,7 +104,7 @@ export function expectDependencies({
     annotateFunction(wrappedGenerate, {name: generate, trait: 'unfulfilled'});
     wrappedGenerate.fulfilled = false;
   } else {
-    wrappedGenerate = function(arg1, arg2) {
+    const callUnderlyingGenerate = ([arg1, arg2], ...extraArgs) => {
       if (hasDataFunction && !arg1) {
         throw new Error(`Expected data`);
       }
@@ -110,14 +118,46 @@ export function expectDependencies({
       }
 
       if (hasDataFunction && hasRelationsFunction) {
-        return generate(arg1, arg2, fulfilledDependencies);
+        return generate(arg1, arg2, ...extraArgs, fulfilledDependencies);
       } else if (hasDataFunction || hasRelationsFunction) {
-        return generate(arg1, fulfilledDependencies);
+        return generate(arg1, ...extraArgs, fulfilledDependencies);
       } else {
-        return generate(fulfilledDependencies);
+        return generate(...extraArgs, fulfilledDependencies);
       }
     };
 
+    if (hasSlotsDescription) {
+      const stationery = fulfilledDependencies.html.stationery({
+        annotation: generate.name,
+
+        // These extra slots are for the data and relations (positional) args.
+        // No hacks to store them temporarily or otherwise "invisibly" alter
+        // the behavior of the template description's `content`, since that
+        // would be expressly against the purpose of templates!
+        slots: {
+          _cfArg1: {validate: v => v.isObject},
+          _cfArg2: {validate: v => v.isObject},
+          ...slots,
+        },
+
+        content(slots) {
+          const args = [slots._cfArg1, slots._cfArg2];
+          return callUnderlyingGenerate(args, slots);
+        },
+      });
+
+      wrappedGenerate = function(...args) {
+        return stationery.template().slots({
+          _cfArg1: args[0] ?? null,
+          _cfArg2: args[1] ?? null,
+        });
+      };
+    } else {
+      wrappedGenerate = function(...args) {
+        return callUnderlyingGenerate(args);
+      };
+    }
+
     wrappedGenerate.fulfill = function() {
       throw new Error(`All dependencies already fulfilled (${generate.name})`);
     };
@@ -165,6 +205,7 @@ export function expectDependencies({
     }
 
     return expectDependencies({
+      slots,
       sprawl,
       relations,
       data,