« get me outta code hell

html: move parseAttributes from replacer into html lib - 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-08-16 15:18:47 -0300
committer(quasar) nebula <qznebula@protonmail.com>2023-08-16 15:18:47 -0300
commitadf0adde987a368298e135c23ce307efbc38d888 (patch)
treed8c47cc91f6b89bdbad95ed26122499e3b5f212d
parent32bfbeab829aad7ec2286f56bad7cd26690e9978 (diff)
html: move parseAttributes from replacer into html lib
It also always returns an html.Attributes object, instead of
a key/value mapping (which would be provided to html.attributes).
-rw-r--r--src/util/html.js64
-rw-r--r--src/util/replacer.js68
2 files changed, 69 insertions, 63 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('"', '&quot;')
       .replaceAll("'", '&apos;');
   }
+
+  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) {
diff --git a/src/util/replacer.js b/src/util/replacer.js
index e1d81319..ac23bf46 100644
--- a/src/util/replacer.js
+++ b/src/util/replacer.js
@@ -276,64 +276,6 @@ function parseNodes(input, i, stopAt, textOnly) {
   return nodes;
 }
 
-function parseAttributes(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 (
-    Object.fromEntries(
-      Object.entries(attributes)
-        .map(([key, val]) => [
-          key,
-          val === 'true'
-            ? true
-            : val === 'false'
-            ? false
-            : val === key
-            ? true
-            : val,
-        ])));
-}
-
 export function postprocessImages(inputNodes) {
   const outputNodes = [];
 
@@ -356,9 +298,9 @@ export function postprocessImages(inputNodes) {
         parseFrom = match.index + match[0].length;
 
         const imageNode = {type: 'image'};
-        const attributes = parseAttributes(match[1]);
+        const attributes = html.parseAttributes(match[1]);
 
-        imageNode.src = attributes.src;
+        imageNode.src = attributes.get('src');
 
         if (previousText.endsWith('\n')) {
           atStartOfLine = true;
@@ -393,9 +335,9 @@ export function postprocessImages(inputNodes) {
           return false;
         })();
 
-        if (attributes.link) imageNode.link = attributes.link;
-        if (attributes.width) imageNode.width = parseInt(attributes.width);
-        if (attributes.height) imageNode.height = parseInt(attributes.height);
+        if (attributes.get('link')) imageNode.link = attributes.get('link');
+        if (attributes.get('width')) imageNode.width = parseInt(attributes.get('width'));
+        if (attributes.get('height')) imageNode.height = parseInt(attributes.get('height'));
 
         outputNodes.push(imageNode);