« 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.js64
1 files changed, 64 insertions, 0 deletions
diff --git a/src/util/html.js b/src/util/html.js
index 19a7d126..712a0a68 100644
--- a/src/util/html.js
+++ b/src/util/html.js
@@ -424,6 +424,10 @@ export function attributes(attributes) {
   return new Attributes(attributes);
 }
 
+export function parseAttributes(string) {
+  return Attributes.parse(string);
+}
+
 export class Attributes {
   #attributes = Object.create(null);
 
@@ -496,6 +500,66 @@ export class Attributes {
       .replaceAll('"', '"')
       .replaceAll("'", ''');
   }
+
+  static parse(string) {
+    const attributes = Object.create(null);
+
+    const skipWhitespace = i => {
+      if (!/\s/.test(string[i])) {
+        return i;
+      }
+
+      const match = string.slice(i).match(/[^\s]/);
+      if (match) {
+        return i + match.index;
+      }
+
+      return string.length;
+    };
+
+    for (let i = 0; i < string.length; ) {
+      i = skipWhitespace(i);
+      const aStart = i;
+      const aEnd = i + string.slice(i).match(/[\s=]|$/).index;
+      const attribute = string.slice(aStart, aEnd);
+      i = skipWhitespace(aEnd);
+      if (string[i] === '=') {
+        i = skipWhitespace(i + 1);
+        let end, endOffset;
+        if (string[i] === '"' || string[i] === "'") {
+          end = string[i];
+          endOffset = 1;
+          i++;
+        } else {
+          end = '\\s';
+          endOffset = 0;
+        }
+        const vStart = i;
+        const vEnd = i + string.slice(i).match(new RegExp(`${end}|$`)).index;
+        const value = string.slice(vStart, vEnd);
+        i = vEnd + endOffset;
+        attributes[attribute] = value;
+      } else {
+        attributes[attribute] = attribute;
+      }
+    }
+
+    return (
+      Reflect.construct(this, [
+        Object.fromEntries(
+          Object.entries(attributes)
+            .map(([key, val]) => [
+              key,
+              (val === 'true'
+                ? true
+             : val === 'false'
+                ? false
+             : val === key
+                ? true
+                : val),
+            ])),
+      ]));
+  }
 }
 
 export function resolve(tagOrTemplate) {