Twentysided Comment Collapser

Adds a button for collapsing comments. Also supports auto-collapsing the comments of certain users.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey, Greasemonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да инсталирате разширение, като например Tampermonkey .

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Violentmonkey.

За да инсталирате този скрипт, трябва да имате инсталирано разширение като Tampermonkey или Userscripts.

За да инсталирате скрипта, трябва да инсталирате разширение като Tampermonkey.

За да инсталирате този скрипт, трябва да имате инсталиран скриптов мениджър.

(Вече имам скриптов мениджър, искам да го инсталирам!)

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да инсталирате разширение като Stylus.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

За да инсталирате този стил, трябва да имате инсталиран мениджър на потребителски стилове.

(Вече имам инсталиран мениджър на стиловете, искам да го инсталирам!)

// ==UserScript==
// @name         Twentysided Comment Collapser
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Adds a button for collapsing comments.  Also supports auto-collapsing the comments of certain users.
// @author       Retsam
// @match        https://www.shamusyoung.com/twentysidedtale/?p=*
// @grant        none
// ==/UserScript==

const usersToCollapseByDefault = [
    /* Add names here to collapse their comments by default.  e.g.: */
    // "Adolf Hitler"
];

const postId = Array.from(document.body.classList)
    .find(n => n.startsWith("postid-"));

// <a href="#" className="comment-body">[Comment Collapsed]</a>
const createCollapsedNode = () => {
    const el = document.createElement("a");
    el.href = "#";
    el.classList.add("comment-body");
    el.textContent = "[Comment Collapsed]";
    return el;
}

// <a href="#" style={marginLeft: 10px}>Hide</a>
const createHideLink = () => {
    const el = document.createElement("a");
    el.href = "#";
    el.style.marginLeft = "10px";
    el.textContent = "Hide";
    return el;
}

// store to persist state across reloads in localStorage
const KEY_PREFIX = "retsam-collapsed-comments-";

const collapsedComments = (() => {
    const savedCommentList = postId && localStorage.getItem(`${KEY_PREFIX}${postId}`);
    try {
        return new Set(JSON.parse(savedCommentList || '[]'));
    } catch(e) {
        return new Set([]);
    }
})();

const saveCollapsedCommentsList = () => {
    if(!postId) return;
    localStorage.setItem(`${KEY_PREFIX}${postId}`, JSON.stringify(Array.from(collapsedComments)));
}

const saveCommentCollapsed = (commentId) => {
    collapsedComments.add(commentId);
    saveCollapsedCommentsList();
}
const saveCommentExpanded = (commentId) => {
    collapsedComments.delete(commentId);
    saveCollapsedCommentsList();
}

const collapseComment = (comment) => {
    const commentBodyNode = comment.querySelector(".comment-body");
    const childrenNode = comment.querySelector(".children");
    const commentId = comment.id || "???";

    saveCommentCollapsed(commentId);

    if(!commentBodyNode) return;

    const collapsedNode = createCollapsedNode();
    const replacedChildren = childrenNode && document.createElement("div");
    commentBodyNode.replaceWith(collapsedNode);
    childrenNode && childrenNode.replaceWith(replacedChildren);

    collapsedNode.addEventListener("click", (e) => {
        e.preventDefault();
        saveCommentExpanded(commentId);
        collapsedNode.replaceWith(commentBodyNode);
        replacedChildren && replacedChildren.replaceWith(childrenNode);
    });
    return collapsedNode; // so the hide link can call "scroll into view"
}

(function() {
    'use strict';

    const $ = document.querySelectorAll.bind(document);
    const allComments = $(".comment");

    // Add a Hide button to each comment
    allComments.forEach(comment => {
        const replyFooter = comment.querySelector(".reply");
        if(!replyFooter) return;
        const hideLink = createHideLink();
        replyFooter.appendChild(hideLink);
        hideLink.addEventListener("click", e => {
            e.preventDefault();
            collapseComment(comment).scrollIntoView();
        });
    });

    allComments.forEach(comment => {
        // Collapse if found in previously collapsed comments list
        // Collapse certain users comments by default, if configured
        const authorNode = comment.querySelector(".comment-author cite");
        const authorIsMuted = authorNode && usersToCollapseByDefault.includes(authorNode.textContent);
        const commentWasCollapsed = collapsedComments.has(comment.id);
        if(authorIsMuted || commentWasCollapsed) {
            collapseComment(comment);
        }
    });
})();