« get me outta code hell

content, replacer: <<label:tooltip>> in content text - hsmusic-wiki - HSMusic - static wiki software cataloguing collaborative creation
about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
author(quasar) nebula <qznebula@protonmail.com>2025-09-18 19:34:06 -0300
committer(quasar) nebula <qznebula@protonmail.com>2025-09-18 19:34:06 -0300
commit2525ba73e915042045851db937d468e144d8870c (patch)
treece5997f415a0ffa4750f68c7ab3375bebf06d747 /src
parentf36fa482e6d9c476c477c8271f2aa46c3744134e (diff)
content, replacer: <<label:tooltip>> in content text preview
Diffstat (limited to 'src')
-rw-r--r--src/content/dependencies/transformContent.js14
-rw-r--r--src/replacer.js70
2 files changed, 80 insertions, 4 deletions
diff --git a/src/content/dependencies/transformContent.js b/src/content/dependencies/transformContent.js
index 4646a6eb..06056ffc 100644
--- a/src/content/dependencies/transformContent.js
+++ b/src/content/dependencies/transformContent.js
@@ -89,6 +89,20 @@ export default {
 
       nodes: parsedNodes
         .map(node => {
+          if (node.type === 'tooltip') {
+            return {
+              i: node.i,
+              iEnd: node.iEnd,
+              type: 'tooltip',
+              data: {
+                // No recursion yet. Sorry!
+                tooltip: node.data.content[0].data,
+                label: node.data.label[0].data,
+                link: null,
+              },
+            };
+          }
+
           if (node.type !== 'tag') {
             return node;
           }
diff --git a/src/replacer.js b/src/replacer.js
index 78f3e104..8a929444 100644
--- a/src/replacer.js
+++ b/src/replacer.js
@@ -190,6 +190,9 @@ const tagHash = '#';
 const tagArgument = '*';
 const tagArgumentValue = '=';
 const tagLabel = '|';
+const tooltipBeginning = '<<';
+const tooltipEnding = '>>';
+const tooltipContent = ':';
 
 const noPrecedingWhitespace = '(?<!\\s)';
 
@@ -208,6 +211,14 @@ const R_tagArgumentValue = escapeRegex(tagArgumentValue);
 
 const R_tagLabel = escapeRegex(tagLabel);
 
+const R_tooltipBeginning =
+  '(?<=[^<]|^)' + escapeRegex(tooltipBeginning) + '(?!<)';
+
+const R_tooltipEnding =
+  '(?<=[^>]|^)' + escapeRegex(tooltipEnding) + '(?!>)';
+
+const R_tooltipContent = escapeRegex(tooltipContent);
+
 const regexpCache = {};
 
 const makeError = (i, message) => ({i, type: 'error', data: {message}});
@@ -247,9 +258,13 @@ function parseNodes(input, i, stopAt, textOnly) {
     }
   };
 
-  const literalsToMatch = stopAt
-    ? stopAt.concat([R_tagBeginning])
-    : [R_tagBeginning];
+  const beginnings = [tagBeginning, tooltipBeginning];
+  const R_beginnings = [R_tagBeginning, R_tooltipBeginning];
+
+  const literalsToMatch =
+    (stopAt
+      ? stopAt.concat(R_beginnings)
+      : R_beginnings);
 
   // The 8ackslash stuff here is to only match an even (or zero) num8er
   // of sequential 'slashes. Even amounts always cancel out! Odd amounts
@@ -300,8 +315,10 @@ function parseNodes(input, i, stopAt, textOnly) {
 
     if (textOnly && closestMatch === tagBeginning)
       throw makeError(i, `Unexpected [[tag]] - expected only text here.`);
+    if (textOnly && closestMatch === tooltipBeginning)
+      throw makeError(i, `Unexpected <<tooltip>> - expected only text here.`);
 
-    const stopHere = closestMatch !== tagBeginning;
+    const stopHere = !beginnings.includes(closestMatch);
 
     iString = i;
     i = closestMatchIndex;
@@ -453,6 +470,51 @@ function parseNodes(input, i, stopAt, textOnly) {
 
       continue;
     }
+
+    if (closestMatch === tooltipBeginning) {
+      const iTooltip = closestMatchIndex;
+
+      let N;
+
+      // Label (hoverable text)
+
+      let label;
+
+      N = parseNodes(input, i, [R_tooltipContent, R_tooltipEnding]);
+
+      if (!stopped)
+        throw endOfInput(i, `reading tooltip label`);
+      if (input.slice(i).startsWith(tooltipEnding))
+        throw makeError(i, `Expected tooltip label and content.`);
+      if (!N.length)
+        throw makeError(i, `Expected tooltip label before content.`);
+
+      label = N;
+      i = stop_iParse;
+
+      // Content (tooltip text)
+
+      let content;
+
+      N = parseNodes(input, i, [R_tooltipEnding]);
+
+      if (!stopped)
+        throw endOfInput(i, `reading tooltip content`);
+      if (!N.length)
+        throw makeError(i, `Expected tooltip content`);
+
+      content = N;
+      i = stop_iParse;
+
+      nodes.push({
+        i: iTooltip,
+        iEnd: i,
+        type: 'tooltip',
+        data: {label, content},
+      });
+
+      continue;
+    }
   }
 
   return nodes;