Markdown Table Of Contents

Creates a table of contents for some markdown-based websites

Verzia zo dňa 26.03.2024. Pozri najnovšiu verziu.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, Greasemonkey alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey, % alebo Violentmonkey.

Na nainštalovanie skriptu si budete musieť nainštalovať rozšírenie, ako napríklad Tampermonkey alebo Userscripts.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie, ako napríklad Tampermonkey.

Na inštaláciu tohto skriptu je potrebné nainštalovať rozšírenie správcu používateľských skriptov.

(Už mám správcu používateľských skriptov, nechajte ma ho nainštalovať!)

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie, ako napríklad Stylus.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

Na inštaláciu tohto štýlu je potrebné nainštalovať rozšírenie správcu používateľských štýlov.

(Už mám správcu používateľských štýlov, nechajte ma ho nainštalovať!)

// ==UserScript==
// @name         Markdown Table Of Contents
// @version      1.0
// @author       Rust1667
// @description  Creates a table of contents for some markdown-based websites
// @match        https://rentry.co/*
// @match        https://rentry.org/*
// @match        https://*.reddit.com/r/*/wiki/*
// @match        https://*.github.io/*
// @match        https://saidit.net/s/*/wiki/*
// @grant        none
// @namespace https://greasyfork.org/users/980489
// ==/UserScript==

(function() {
    'use strict';

    let currentPageUrl = window.location.href;
    let indexContainer = null;

    function createIndex() {
        let subheaderSelector = 'h2[id], h3[id], h4[id], h5[id], h6[id]';

        // Check if there is more than one h1 subheader
        if (document.querySelectorAll('h1[id]').length > 1) {
            subheaderSelector = 'h1[id], ' + subheaderSelector;
        }

        const subheaders = document.querySelectorAll(subheaderSelector);
        if (subheaders.length === 0) {
            removeIndex();
            return;
        }

        // Determine the highest subheader tier
        let highestTier = 7; // Set to 7 to ensure padding is always greater
        subheaders.forEach(subheader => {
            const level = parseInt(subheader.tagName[1]);
            if (level < highestTier) {
                highestTier = level;
            }
        });

        // Remove existing index container if it exists
        if (indexContainer) {
            indexContainer.remove();
        }

        indexContainer = document.createElement('div');
        indexContainer.style.position = 'fixed';
        indexContainer.style.top = '50%';
        indexContainer.style.right = '0';
        indexContainer.style.transform = 'translateY(-50%)'; // Adjust to center vertically
        indexContainer.style.backgroundColor = getComputedStyle(document.body).getPropertyValue('background-color');
        indexContainer.style.border = '1px solid #ced4da';
        indexContainer.style.padding = '0'; // Remove padding
        indexContainer.style.zIndex = '9999';
        indexContainer.style.maxHeight = '80vh';
        indexContainer.style.overflowY = 'auto';
        indexContainer.style.maxWidth = '200px'; // Limit maximum width

        const indexList = document.createElement('ul');
        indexList.style.margin = '0'; // Remove margin
        indexList.style.padding = '0'; // Remove padding
        indexList.style.listStyleType = 'none'; // Remove bullet points

        subheaders.forEach(subheader => {
            const listItem = document.createElement('li');
            const link = document.createElement('a');
            let textContent = subheader.textContent.trim();
            // Trim long titles
            if (textContent.length > 20) {
                textContent = textContent.substring(0, 20) + '...';
            }
            link.textContent = textContent;
            link.href = '#' + subheader.id;
            link.style.whiteSpace = 'nowrap'; // Prevent line breaks
            link.style.overflow = 'hidden'; // Hide overflowing text
            link.style.textOverflow = 'ellipsis'; // Add ellipsis for overflow
            const level = parseInt(subheader.tagName[1]);
            listItem.style.paddingLeft = (level - highestTier) * 2 + 'em'; // Adjust padding based on the difference from the highest tier
            indexList.appendChild(listItem);
            listItem.appendChild(link);
        });

        indexContainer.appendChild(indexList);
        document.body.appendChild(indexContainer);
    }

    function removeIndex() {
        if (indexContainer) {
            indexContainer.remove();
            indexContainer = null;
        }
    }

    function checkUrlChange() {
        const newUrl = window.location.href;
        if (newUrl !== currentPageUrl) {
            currentPageUrl = newUrl;
            createIndex();
        } else if (!document.querySelector('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]')) {
            // Page URL hasn't changed, but no subheaders found
            removeIndex();
        }
    }

    // Check if the page has subheaders that can be linked to with a URL
    const hasSubheaders = document.querySelector('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]');
    if (hasSubheaders) {
        createIndex();
        // Uncommenting the interval check
        setInterval(checkUrlChange, 1000); // Check for URL change every second
    }
})();