]> git.ardis.lu - simulate-etherscan-function-display/commitdiff
Initial commit
authorArdis Lu <ardisglu@gmail.com>
Fri, 7 Jul 2023 08:37:27 +0000 (01:37 -0700)
committerArdis Lu <ardisglu@gmail.com>
Fri, 7 Jul 2023 08:37:27 +0000 (01:37 -0700)
README.md [new file with mode: 0644]
index.html [new file with mode: 0644]

diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..18eac81
--- /dev/null
+++ b/README.md
@@ -0,0 +1,3 @@
+# simulate-etherscan-function-display
+
+This is a web utility to simulate how Solidity functions will display on Etherscan's UI.
diff --git a/index.html b/index.html
new file mode 100644 (file)
index 0000000..23f47a1
--- /dev/null
@@ -0,0 +1,192 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+  <meta charset="UTF-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>simulate-etherscan-function-display</title>
+  <link rel="icon" href="data:,">
+  <style>
+    @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
+
+    body {
+      font-family: "Roboto", system-ui, -apple-system, "Segoe UI", "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+      font-size: 0.9062rem;
+      background: hsl(216deg 50% 98%);
+    }
+
+    header {
+      display: flex;
+      flex-direction: column;
+      align-items: center;
+    }
+
+    h1 {
+      margin: 0;
+    }
+
+    main {
+      display: flex;
+      flex-direction: column;
+      inline-size: min(100dvi - 16px, 1080px);
+      margin-inline: auto;
+    }
+
+    label,
+    h2 {
+      font-size: 1.25rem;
+      font-weight: 700;
+      inline-size: 100%;
+      margin: 0;
+      margin-block-end: 4px;
+    }
+
+    textarea {
+      box-sizing: border-box;
+      font-size: 1rem;
+      min-inline-size: 100%;
+      min-block-size: 10ch;
+      block-size: 40dvb;
+      margin-block-end: 16px;
+      resize: vertical;
+      padding: 8px;
+      border-radius: 6px;
+      border: 1px solid rgb(0 0 0 / 0.1);
+    }
+
+    div.pill-container {
+      display: flex;
+      flex-wrap: wrap;
+      gap: 8px;
+    }
+
+    span.pill {
+      position: relative;
+      --tooltip-opacity: 0;
+      --tooltip-visibility: hidden;
+    }
+
+    span.pill:has(.pill-text:hover) {
+      --tooltip-opacity: 1;
+      --tooltip-visibility: visible;
+    }
+
+    span.pill-text {
+      display: block;
+      box-sizing: border-box;
+      inline-size: 100%;
+      max-inline-size: 95px;
+      font-size: 0.75em;
+      font-weight: 400;
+      text-align: center;
+      line-height: 1;
+      padding-block: 0.375rem;
+      padding-inline: 0.75em;
+      background: rgb(248 249 250);
+      border-radius: 6px;
+      border: 1px solid rgb(0 0 0 / 0.1);
+      overflow: hidden;
+      text-overflow: ellipsis;
+      white-space: nowrap;
+    }
+
+    span.tooltip {
+      position: absolute;
+      inset-block: 0;
+      inset-inline-start: 50%;
+      transform: translate(-50%, calc(-100% - 6px));
+      font-size: 0.78515625rem;
+      line-height: 1;
+      inline-size: max-content;
+      padding: 0.4rem;
+      border-radius: 8px;
+      background: rgb(8 29 53);
+      color: rgb(255 255 255);
+      visibility: var(--tooltip-visibility);
+      opacity: var(--tooltip-opacity);
+      transition: opacity 150ms linear;
+    }
+
+    span.tooltip::after {
+      content: "";
+      position: absolute;
+      inset-block-start: 100%;
+      inset-inline-start: 50%;
+      transform: translateX(-50%);
+      inline-size: 0.8rem;
+      block-size: 0.4rem;
+      background: rgb(8 29 53);
+      clip-path: polygon(0 0, 100% 0, 50% 90%);
+    }
+  </style>
+</head>
+
+<body>
+  <header>
+    <h1>Simulate Etherscan function display</h1>
+    <p>Enter Solidity functions into the text area below to preview how the function pills will display in the Etherscan UI.</p>
+  </header>
+
+  <main>
+    <label for="functions">Solidity functions</label>
+    <textarea name="functions" id="functions" placeholder="function totalSupply() external view returns (uint256)" autocomplete="off"></textarea>
+
+    <h2>Simulated Etherscan function pills</h2>
+    <div class="pill-container"></div>
+  </main>
+
+  <script type="module">
+    // Extract all function names from arbitrary Solidity code
+    function getFunctions(code) {
+      const re = /^(function )?(?<name>[\w]+)\(.*?\)/;
+      const functions = [];
+      for (let line of code.split('\n')) {
+        line = line.trim();
+        const name = re.exec(line)?.groups?.name;
+        if (name) {
+          functions.push(name);
+        }
+      }
+      return functions;
+    }
+
+    // Converts a camelCase string into Title Case With Spaces for human readability.
+    function camelCaseToTitleCase(str) {
+      str = str[0].toLocaleUpperCase() + str.slice(1);
+      return str.replaceAll(/([A-Z]+)/g, ' $1').slice(1);
+    }
+
+    function debounce(fn, wait) {
+      let timeoutId;
+      return () => {
+        clearTimeout(timeoutId);
+        timeoutId = setTimeout(fn, wait);
+      }
+    }
+
+    const textarea = document.querySelector('textarea');
+    const pillContainer = document.querySelector('.pill-container');
+    textarea.addEventListener('input', debounce(() => {
+      const functions = getFunctions(textarea.value);
+      if (functions.length === 0) {
+        return;
+      }
+
+      pillContainer.innerHTML = '';
+      let tooltipCounter = 1;
+      for (const fn of functions) {
+        const displayName = camelCaseToTitleCase(fn);
+        const pillName = displayName.length > 16 ? `${displayName.slice(0, 16)}...` : displayName;
+        const tooltipId = `tooltip${tooltipCounter}`;
+        pillContainer.insertAdjacentHTML('beforeend', `
+          <span class="pill">
+            <span class="pill-text" aria-describedby="${tooltipId}">${pillName}</span>
+            <span class="tooltip" role="tooltip" id="${tooltipId}">${displayName}</span>
+          </span>`);
+        tooltipCounter++;
+      }
+    }, 250));
+  </script>
+</body>
+
+</html>
\ No newline at end of file
This page took 0.041868 seconds and 4 git commands to generate.