From 0110beab32f724635e72b722a022e611f6218423 Mon Sep 17 00:00:00 2001
From: SansGuidon <sansguidon@noreply.gitea.zoemp.be>
Date: Thu, 28 Nov 2024 13:34:25 +0000
Subject: [PATCH] Add tampermonkey/hn_url_highlighter_with_preview.js

---
 .../hn_url_highlighter_with_preview.js        | 108 ++++++++++++++++++
 1 file changed, 108 insertions(+)
 create mode 100644 tampermonkey/hn_url_highlighter_with_preview.js

diff --git a/tampermonkey/hn_url_highlighter_with_preview.js b/tampermonkey/hn_url_highlighter_with_preview.js
new file mode 100644
index 0000000..f630ee7
--- /dev/null
+++ b/tampermonkey/hn_url_highlighter_with_preview.js
@@ -0,0 +1,108 @@
+// ==UserScript==
+// @name         Hacker News URL Highlighter with Preview
+// @namespace    https://news.ycombinator.com/
+// @version      1.3
+// @description  Highlights URLs in comments on Hacker News, lists them in a panel, and provides export functionality. Hover previews only in comments.
+// @author       MorganGeek
+// @match        https://news.ycombinator.com/item?id=*
+// @grant        GM_xmlhttpRequest
+// @grant        GM_setClipboard
+// @connect      *
+// @run-at       document-end
+// ==/UserScript==
+
+(function () {
+    'use strict';
+
+    // Create a floating panel for displaying URLs
+    const panel = document.createElement('div');
+    panel.id = 'url-panel';
+    panel.style.position = 'fixed';
+    panel.style.top = '10px';
+    panel.style.right = '10px';
+    panel.style.backgroundColor = '#fff';
+    panel.style.border = '1px solid #ccc';
+    panel.style.borderRadius = '5px';
+    panel.style.padding = '10px';
+    panel.style.boxShadow = '0px 0px 10px rgba(0,0,0,0.2)';
+    panel.style.maxHeight = '80vh';
+    panel.style.overflowY = 'auto';
+    panel.style.zIndex = 1000;
+    panel.innerHTML = '<h4>URLs</h4><ul id="url-list" style="margin: 0; padding: 0; list-style: none;"></ul><button id="copy-urls" style="margin-top: 10px; display: block; width: 100%;">Copy URLs</button>';
+    document.body.appendChild(panel);
+
+    // Tooltip for previews
+    const tooltip = document.createElement('div');
+    tooltip.id = 'url-tooltip';
+    tooltip.style.position = 'absolute';
+    tooltip.style.backgroundColor = '#fff';
+    tooltip.style.border = '1px solid #ccc';
+    tooltip.style.borderRadius = '5px';
+    tooltip.style.padding = '5px';
+    tooltip.style.boxShadow = '0px 0px 10px rgba(0,0,0,0.2)';
+    tooltip.style.maxWidth = '300px';
+    tooltip.style.display = 'none';
+    tooltip.style.zIndex = 1001;
+    document.body.appendChild(tooltip);
+
+    const urlSet = new Set();
+
+    // Extract URLs from comments and highlight them
+    const comments = document.querySelectorAll('.commtext');
+    comments.forEach(comment => {
+        const links = comment.querySelectorAll('a[href]');
+        links.forEach(link => {
+            const url = link.href;
+            if (!urlSet.has(url)) {
+                urlSet.add(url);
+                link.style.backgroundColor = '#ffff99'; // Highlight the link
+
+                // Add the URL to the floating panel
+                const listItem = document.createElement('li');
+                listItem.textContent = url;
+                listItem.style.marginBottom = '5px';
+                listItem.style.wordWrap = 'break-word';
+                listItem.style.cursor = 'pointer';
+                listItem.dataset.url = url;
+                document.getElementById('url-list').appendChild(listItem);
+            }
+
+            // Add hover preview functionality to comment links
+            link.addEventListener('mouseover', () => {
+                GM_xmlhttpRequest({
+                    method: 'GET',
+                    url: url,
+                    onload: response => {
+                        tooltip.innerHTML = '';
+                        const parser = new DOMParser();
+                        const doc = parser.parseFromString(response.responseText, 'text/html');
+                        const title = doc.querySelector('title') ? doc.querySelector('title').innerText : 'No Title';
+                        const description = doc.querySelector('meta[name="description"]') ? doc.querySelector('meta[name="description"]').content : 'No Description';
+
+                        tooltip.innerHTML = `<strong>${title}</strong><p>${description}</p>`;
+                        tooltip.style.display = 'block';
+                    },
+                    onerror: () => {
+                        tooltip.innerHTML = '<strong>Preview unavailable</strong>';
+                        tooltip.style.display = 'block';
+                    }
+                });
+
+                const rect = link.getBoundingClientRect();
+                tooltip.style.top = `${rect.bottom + window.scrollY + 5}px`;
+                tooltip.style.left = `${rect.left + window.scrollX}px`;
+            });
+
+            link.addEventListener('mouseout', () => {
+                tooltip.style.display = 'none';
+            });
+        });
+    });
+
+    // Handle the Copy URLs button
+    document.getElementById('copy-urls').addEventListener('click', () => {
+        const urlArray = Array.from(urlSet);
+        GM_setClipboard(urlArray.join('\n'), 'text');
+        alert('URLs copied to clipboard!');
+    });
+})();