« 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/util/html.js52
1 files changed, 36 insertions, 16 deletions
diff --git a/src/util/html.js b/src/util/html.js
index 49816990..499e3724 100644
--- a/src/util/html.js
+++ b/src/util/html.js
@@ -82,29 +82,33 @@ export const noEdgeWhitespace = Symbol();
 // character).
 export const blockwrap = Symbol();
 
-// Note: This is only guaranteed to return true for blanks (as returned by
-// html.blank()) and false for Tags and Templates (regardless of contents or
-// other properties). Don't depend on this to match any other values.
-export function isBlank(value) {
-  if (value instanceof Tag) {
-    return false;
+// Checks if the content provided would be represented as nothing if included
+// on a page. This can be used on its own, and is the underlying "interface"
+// layer for specific classes' `blank` getters, so its definition and usage
+// tend to be recursive.
+//
+// Note that this shouldn't be used to infer anything about non-content values
+// (e.g. attributes) - it's only suited for actual page content.
+export function isBlank(content) {
+  if (content instanceof Tag || content instanceof Template) {
+    return content.blank;
   }
 
-  if (value instanceof Template) {
-    return false;
+  if (Array.isArray(content)) {
+    return content.every(isBlank);
   }
 
-  if (!Array.isArray(value)) {
-    return false;
+  if (typeof content === 'string') {
+    return content.length === 0;
   }
 
-  return value.length === 0;
+  return false;
 }
 
 export const validators = {
   isBlank(value) {
     if (!isBlank(value)) {
-      throw new TypeError(`Expected html.blank()`);
+      throw new TypeError(`Expected blank content`);
     }
 
     return true;
@@ -292,6 +296,18 @@ export class Tag {
     }
   }
 
+  get blank() {
+    if (this.onlyIfContent && isBlank(this.content)) {
+      return true;
+    }
+
+    if (this.contentOnly && isBlank(this.content)) {
+      return true;
+    }
+
+    return false;
+  }
+
   get contentOnly() {
     if (this.tagName !== '') return false;
     if (!this.attributes.blank) return false;
@@ -366,13 +382,13 @@ export class Tag {
   }
 
   toString() {
-    const attributesString = this.attributes.toString();
-    const contentString = this.content.toString();
-
-    if (this.onlyIfContent && !contentString) {
+    if (this.onlyIfContent && isBlank(this.content)) {
       return '';
     }
 
+    const attributesString = this.attributes.toString();
+    const contentString = this.content.toString();
+
     if (!this.tagName) {
       return contentString;
     }
@@ -1359,6 +1375,10 @@ export class Template {
     return this.#description;
   }
 
+  get blank() {
+    return isBlank(this.content);
+  }
+
   toString() {
     return this.content.toString();
   }