Feel free to use this, I think it works. You can tweak it yourself or throw it in some chatbot and tell it to edit it if you want. Right now it only shows replies on hover, and you can't click to nest replies.
[code]// ==UserScript==
// @name Wapchan Reply Links with Hover
// @namespace
http://tampermonkey.net/// @version 0.8
// @description Adds links to posts that reply to the current post on wapchan.org with hover previews, excluding backlinks
// @author Anonymous
// @match
https://wapchan.org/*// @grant none
// ==/UserScript==
(function() {
'use strict';
// Create the hover preview div
let hoverDiv = document.createElement('div');
hoverDiv.className = 'postHover';
hoverDiv.style.display = 'none'; // Hidden by default
document.body.appendChild(hoverDiv);
// Inject CSS styles for the hover preview and reply links
let style = document.createElement('style');
style.textContent = `
.postHover {
position: absolute;
z-index: 1000;
background: white;
border: 1px solid black;
padding: 5px;
max-width: 500px;
max-height: 300px;
overflow: auto;
}
.reply-links {
margin-left: 5px;
font-size: 0.9em;
}
.reply-link {
text-decoration: none;
color: #0000EE;
}
.reply-link:visited {
color: #0000EE; /* Same color for visited links */
}
.reply-link:hover {
text-decoration: underline;
}
`;
document.head.appendChild(style);
// Process all posts on the page
let posts = document.querySelectorAll('.post');
posts.forEach(function(post) {
// Extract the post number from the post's ID (e.g., "op_184" or "reply_185")
let postId = post.id;
let postNumber;
if (postId.startsWith('op_')) {
postNumber = postId.slice(3);
} else if (postId.startsWith('reply_')) {
postNumber = postId.slice(6);
} else {
return; // Skip if not a post
}
// Find posts this post replies to (to filter them out)
let body = post.querySelector('.body');
let backlinkNumbers = new Set();
if (body) {
let backlinks = body.querySelectorAll('a[href*="#"]');
backlinks.forEach(function(backlink) {
if (!backlink.textContent.startsWith('>>')) return;
let href = backlink.getAttribute('href');
let refPostNumber = href.split('#')[1];
if (refPostNumber && refPostNumber !== postNumber) {
backlinkNumbers.add(refPostNumber);
}
});
}
// Find all quotelinks that reference this post (posts replying to it)
let quotelinks = document.querySelectorAll(`a[href*="#${postNumber}"]`);
// Collect unique post numbers of posts that reply to this one, excluding backlinks
let replyingPostNumbers = new Set();
quotelinks.forEach(function(quotelink) {
if (!quotelink.textContent.startsWith('>>')) return; // Ensure it's a quotelink
let replyingPost = quotelink.closest('.post');
if (replyingPost) {
let refPostId = replyingPost.id;
let refPostNumber;
if (refPostId.startsWith('op_')) {
refPostNumber = refPostId.slice(3);
} else if (refPostId.startsWith('reply_')) {
refPostNumber = refPostId.slice(6);
}
if (refPostNumber && refPostNumber !== postNumber && !backlinkNumbers.has(refPostNumber)) {
replyingPostNumbers.add(refPostNumber);
}
}
});
// If there are posts replying to this one, add reply links to the header
if (replyingPostNumbers.size > 0) {
let replyLinksSpan = document.createElement('span');
replyLinksSpan.className = 'reply-links';
replyLinksSpan.textContent = 'Replies: ';
// Create a reply link for each post that replies to this one
replyingPostNumbers.forEach(function(refPostNumber) {
let link = document.createElement('a');
link.href = '#' + refPostNumber;
link.className = 'reply-link';
link.textContent = '>>' + refPostNumber;
// Hover event: Show the preview
link.addEventListener('mouseover', function(event) {
let href = this.getAttribute('href'); // e.g., "#186"
let targetPostId = href.slice(1); // e.g., "186"
let referencedPost = document.getElementById('reply_' + targetPostId) || document.getElementById('op_' + targetPostId);
if (referencedPost) {
hoverDiv.innerHTML = referencedPost.innerHTML;
hoverDiv.style.left = (event.pageX + 10) + 'px';
hoverDiv.style.top = (event.pageY + 10) + 'px';
hoverDiv.style.display = 'block';
}
});
// Mouseout event: Hide the preview
link.addEventListener('mouseout', function() {
hoverDiv.style.display = 'none';
});
replyLinksSpan.appendChild(link);
replyLinksSpan.appendChild(document.createTextNode(' '));
});
// Append the reply links span to the post's intro (p.intro)
let intro = post.querySelector('.intro');
if (intro) {
intro.appendChild(replyLinksSpan);
}
}
});
})();[/code]