« get me outta code hell

hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src/util/html.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/html.js')
-rw-r--r--src/util/html.js63
1 files changed, 44 insertions, 19 deletions
diff --git a/src/util/html.js b/src/util/html.js
index a311bbba..282a52da 100644
--- a/src/util/html.js
+++ b/src/util/html.js
@@ -2,7 +2,7 @@
 
 import {inspect} from 'node:util';
 
-import {empty} from '#sugar';
+import {empty, typeAppearance} from '#sugar';
 import * as commonValidators from '#validators';
 
 // COMPREHENSIVE!
@@ -242,7 +242,7 @@ export class Tag {
       this.selfClosing &&
       !(value === null ||
         value === undefined ||
-        !Boolean(value) ||
+        !value ||
         Array.isArray(value) && value.filter(Boolean).length === 0)
     ) {
       throw new Error(`Tag <${this.tagName}> is self-closing but got content`);
@@ -633,7 +633,7 @@ export class Template {
 
   static validateDescription(description) {
     if (typeof description !== 'object') {
-      throw new TypeError(`Expected object, got ${typeof description}`);
+      throw new TypeError(`Expected object, got ${typeAppearance(description)}`);
     }
 
     if (description === null) {
@@ -806,24 +806,43 @@ export class Template {
     }
 
     // Null is always an acceptable slot value.
-    if (value !== null) {
-      if ('validate' in description) {
-        description.validate({
-          ...commonValidators,
-          ...validators,
-        })(value);
-      }
+    if (value === null) {
+      return true;
+    }
+
+    if ('validate' in description) {
+      description.validate({
+        ...commonValidators,
+        ...validators,
+      })(value);
+    }
 
-      if ('type' in description) {
-        const {type} = description;
-        if (type === 'html') {
-          if (!isHTML(value)) {
+    if ('type' in description) {
+      switch (description.type) {
+        case 'html': {
+          if (!isHTML(value))
             throw new TypeError(`Slot expects html (tag, template or blank), got ${typeof value}`);
-          }
-        } else {
-          if (typeof value !== type) {
-            throw new TypeError(`Slot expects ${type}, got ${typeof value}`);
-          }
+
+          return true;
+        }
+
+        case 'string': {
+          // Tags and templates are valid in string arguments - they'll be
+          // stringified when exposed to the description's .content() function.
+          if (isTag(value) || isTemplate(value))
+            return true;
+
+          if (typeof value !== 'string')
+            throw new TypeError(`Slot expects string, got ${typeof value}`);
+
+          return true;
+        }
+
+        default: {
+          if (typeof value !== description.type)
+            throw new TypeError(`Slot expects ${description.type}, got ${typeof value}`);
+
+          return true;
         }
       }
     }
@@ -847,6 +866,12 @@ export class Template {
       return providedValue;
     }
 
+    if (description.type === 'string') {
+      if (isTag(providedValue) || isTemplate(providedValue)) {
+        return providedValue.toString();
+      }
+    }
+
     if (providedValue !== null) {
       return providedValue;
     }