Jump to content

User:GrabUp/test.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// Ensure MediaWiki modules are loaded before running the script 
mw.loader.using(['mediawiki.util', 'mediawiki.api']).then(function() {
    const api = new mw.Api();

    // List of unreliable sources and specific subsections to highlight
const unreliableSources = [
    "imdb.com", 
    "example.com", 
    "youtube.com", 
    "medium.com", 
    "reddit.com", 
    "republicworld.com", 
    "opindia.com", 
    "bollywoodlife.com",
    { domain: "khaleejtimes.com", path: "/kt-network/" }, // Example of a specific subsection to treat as unreliable
    { domain: "abplive.com", path: "/brand-wire/" },
    { domain: "charlotteobserver.com", path: "/contributor-content/" },
    { domain: "dailyrecord.co.uk", path: "/special-features/" },
    { domain: "deccanherald.com", path: "/brandspot/" },
    { domain: "digitaljournal.com", path: "/pr/" },
    { domain: "hindustantimes.com", path: "/brand-stories/" },
    { domain: "hindustantimes.com", path: "/brand-post/" },
    { domain: "indiatoday.in", path: "/impact-feature/" },
    { domain: "jpost.com", path: "/brandblend/" },
    { domain: "laprogressive.com", path: "/sponsored/" },
    { domain: "liverpoolecho.co.uk", path: "/special-features/" },
    { domain: "manchestereveningnews.co.uk", path: "/special-features/" },
    { domain: "maxim.com", path: "/partner/" },
    { domain: "livemint.com", path: "/brand-stories/" },
    { domain: "miamiherald.com", path: "/contributor-content/" },
    { domain: "mid-day.com", path: "/brand-media/" },
    { domain: "nytimes.com", path: "/paidpost/" },
    { domain: "timesofindia.indiatimes.com", path: "/spotlight/" },
    { domain: "timesofindia.indiatimes.com", path: "/entertainment/spotlight/" },
    { domain: "thequint.com", path: "/brandstudio/" },
    { domain: "tribuneindia.com", path: "/news/brand-connect/" },
    { domain: "usatoday.com", path: "/sponsor-story/" },
    { domain: "usatoday.com", path: "/special/contributor-content/" }
];

// Add the "Citation Remover" button to the "Actions" section in the toolbar
var citationRemoverButton = mw.util.addPortletLink(
    'p-cactions',  // Add to the "Actions" section
    '#',
    'Citation Remover',
    'ca-manage-citations',
    'List and manage article citations'
);

// Function to force the position of the button in the "Actions" section
function fixButtonPosition() {
    var toolbar = document.getElementById('p-cactions').getElementsByTagName('ul')[0];
    var button = document.getElementById('ca-manage-citations');
    
    // Specify 'prepend' to place at the top, or 'append' to place at the bottom
    toolbar.appendChild(button); // Replace with toolbar.insertBefore(button, toolbar.firstChild) to place it at the top
}

// Run fixButtonPosition once the page is fully loaded
$(document).ready(function() {
    fixButtonPosition();
});

document.getElementById('ca-manage-citations').addEventListener('click', function(event) {
    event.preventDefault();
    loadCitations();
});

function parseCitation(content) {
    const titleMatch = content.match(/\|title\s*=\s*([^|]+)/);
    const siteMatch = content.match(/\|website\s*=\s*([^|]+)/);
    const dateMatch = content.match(/\|date\s*=\s*([^|]+)/);

    // Match both <ref>[https://example.com Example]</ref> and <ref>https://example.com Example</ref>
    const urlMatch = content.match(/\|url\s*=\s*([^|]+)/) || 
                     content.match(/\[([^\s]+)(?:\s+[^\]]*)?\]/) || 
                     content.match(/<ref>(https?:\/\/[^\s]+)(?:\s+(.+?))?<\/ref>/);

    const url = urlMatch ? urlMatch[1].trim() : "#";
    const site = siteMatch ? siteMatch[1].trim() : (url !== "#" ? new URL(url).hostname : "Unknown Source");
    const title = titleMatch ? titleMatch[1].trim() : (urlMatch && urlMatch[2] ? urlMatch[2].trim() : url);
    const date = dateMatch ? dateMatch[1].trim() : "";

    // Determine if the citation is unreliable based on domain or specific path
    const isUnreliable = unreliableSources.some(source => {
        if (typeof source === "string") {
            // Simple domain-based check
            return site.includes(source) || url.includes(source);
        } else if (source.domain && source.path) {
            // Check for specific domain and path within URL
            const domainRegex = new RegExp(`^(https?://)?(www\.)?${source.domain}`);
            const pathRegex = new RegExp(`${source.path}`);
            return domainRegex.test(url) && pathRegex.test(url);
        }
        return false;
    });

    // Debug log for testing
    console.log("Checked URL:", url, "| Title:", title, "| Is Unreliable:", isUnreliable);

    return {
        originalText: content,
        title: title,
        site: site,
        date: date,
        url: url,
        isUnreliable: isUnreliable
    };
}

    function loadCitations() {
        api.get({
            action: "query",
            titles: mw.config.get('wgPageName'),
            prop: "revisions",
            rvprop: "content",
            formatversion: "2"
        }).then(function(data) {
            const pageContent = data.query.pages[0].revisions[0].content;
            const citations = extractCitations(pageContent);
            displayCitationsPopup(citations);
        }).catch(console.error);
    }

    function extractCitations(content) {
        const refTagRegex = /<ref\b[^>]*?\/>|<ref\b[^>]*?>.*?<\/ref>/gs;
        const citations = [];
        const citationMap = {}; // Track all citations by name to count shortcuts
        let match;

        while ((match = refTagRegex.exec(content)) !== null) {
            const refTag = match[0];
            const nameAttrMatch = refTag.match(/name=["']([^"']+)["']/);
            const refName = nameAttrMatch ? nameAttrMatch[1] : null;

            if (refName) {
                if (/\/>$/.test(refTag)) {
                    citationMap[refName] = citationMap[refName] || { shortcutCount: 0, mainIndex: null };
                    citationMap[refName].shortcutCount += 1;
                } else {
                    const citation = parseCitation(refTag);
                    citation.refName = refName;
                    citation.shortcutCount = citationMap[refName] ? citationMap[refName].shortcutCount : 0;
                    citations.push(citation);

                    citationMap[refName] = { shortcutCount: 0, mainIndex: citations.length - 1 };
                }
            } else {
                citations.push(parseCitation(refTag));
            }
        }

        return citations;
    }


    function displayCitationsPopup(citations) {
        const popup = document.createElement("div");
        popup.id = "citation-popup";
        popup.style.position = "fixed";
        popup.style.top = "50%";
        popup.style.left = "50%";
        popup.style.transform = "translate(-50%, -50%)";
        popup.style.padding = "20px";
        popup.style.backgroundColor = "#1e1e1e";  // Dark background
        popup.style.border = "2px solid #3a3a3a";  // Darker border for subtle contrast
        popup.style.borderRadius = "12px";
        popup.style.zIndex = "1000";
        popup.style.width = "600px";
        popup.style.maxHeight = "80%";
        popup.style.overflow = "hidden";
        popup.style.boxShadow = "0px 8px 16px rgba(0, 0, 0, 0.7)";

         // Title bar
        const titleBar = document.createElement("div");
        titleBar.style.textAlign = "center";
        titleBar.style.fontSize = "20px";
        titleBar.style.fontWeight = "bold";
        titleBar.style.marginBottom = "15px";
        titleBar.style.color = "#4ea8ff";  // Light blue color for title


        const linkGrabUp = document.createElement("a");
        linkGrabUp.href = "https://en.wikipedia.org/wiki/User:GrabUp";
        linkGrabUp.textContent = "GrabUp";
        linkGrabUp.style.color = "#4ea8ff"; // Ensure the link has the same color
        linkGrabUp.style.textDecoration = "none"; // Optional: remove underline


        const linkTalk = document.createElement("a");
        linkTalk.href = "https://en.wikipedia.org/wiki/User_talk:GrabUp";
        linkTalk.textContent = " (Talk)";
        linkTalk.style.color = "#4ea8ff"; // Ensure the link has the same color
        linkTalk.style.textDecoration = "none"; // Optional: remove underline

        // Create the full title text
        const titleText = document.createTextNode("Citation Remover by ");

        // Append the text and links to the title bar
        titleBar.appendChild(titleText);
        titleBar.appendChild(linkGrabUp);
        titleBar.appendChild(linkTalk);

        popup.appendChild(titleBar);

        // Close button in top-right corner
        const closeButton = document.createElement("button");
        closeButton.innerHTML = "&times;";
        closeButton.style.position = "absolute";
        closeButton.style.top = "10px";
        closeButton.style.right = "10px";
        closeButton.style.border = "none";
        closeButton.style.background = "transparent";
        closeButton.style.fontSize = "24px";
        closeButton.style.cursor = "pointer";
        closeButton.style.color = "#4ea8ff";  // Light blue color for close button
        closeButton.addEventListener("click", () => popup.remove());
        popup.appendChild(closeButton);

        if (citations.length === 0) {
            const message = document.createElement("p");
            message.textContent = "No citations found in this article.";
            message.style.fontSize = "16px";
            message.style.textAlign = "center";
            message.style.color = "#ffffff";  // Light text color
            popup.appendChild(message);
        } else {
            const listContainer = document.createElement("div");
            listContainer.style.maxHeight = "400px";
            listContainer.style.overflowY = "auto";
            listContainer.style.marginBottom = "10px";

            const list = document.createElement("ol");
            citations.forEach((citation, index) => {
                const listItem = document.createElement("li");
                listItem.style.marginBottom = "15px";

                const shortcutText = citation.shortcutCount > 0 ? 
                    `(used ${citation.shortcutCount} more time${citation.shortcutCount > 1 ? 's' : ''})` : "";

                listItem.innerHTML = `
                    <input type="checkbox" class="citation-checkbox" data-index="${index}">
                    <span style="color: ${citation.isUnreliable ? "tomato" : "#e0e0e0"}; font-size: 16px;">
                        <a href="${citation.url}" target="_blank" style="color: ${citation.isUnreliable ? "tomato" : "#4ea8ff"}; font-weight: bold; font-size: 18px;">
                            ${index + 1}. ${citation.title} <!-- Added numbering here -->
                        </a>
                        <br> <strong>${citation.site}</strong>, ${citation.date} ${shortcutText}
                        ${citation.isUnreliable ? '<br><small style="color: tomato;">Unreliable source</small>' : ""}
                    </span>
                `;
                list.appendChild(listItem);
            });
            
const selectAllButton = document.createElement("button");
selectAllButton.textContent = "Select All";
selectAllButton.style.padding = "8px 12px";
selectAllButton.style.marginBottom = "10px";
selectAllButton.style.backgroundColor = "#4ea8ff"; // Light blue color
selectAllButton.style.color = "white";
selectAllButton.style.border = "none";
selectAllButton.style.borderRadius = "6px";
selectAllButton.style.cursor = "pointer";

selectAllButton.addEventListener("click", function() {
    const checkboxes = document.querySelectorAll(".citation-checkbox");
    checkboxes.forEach(checkbox => checkbox.checked = true);
});

listContainer.appendChild(selectAllButton);

            listContainer.appendChild(list);
            popup.appendChild(listContainer);

            // Fixed "Remove Citations" button
            const buttonContainer = document.createElement("div");
            buttonContainer.style.position = "absolute";
            buttonContainer.style.bottom = "10px";
            buttonContainer.style.width = "100%";
            buttonContainer.style.display = "flex";
            buttonContainer.style.justifyContent = "center";

            const removeSelectedButton = document.createElement("button");
            removeSelectedButton.textContent = "Remove Citations";
            removeSelectedButton.style.padding = "10px 15px";
            removeSelectedButton.style.border = "none";
            removeSelectedButton.style.backgroundColor = "#d9534f";  // Red for remove button
            removeSelectedButton.style.color = "white";
            removeSelectedButton.style.borderRadius = "8px";
            removeSelectedButton.style.cursor = "pointer";
            removeSelectedButton.addEventListener("click", function() {
                const selectedCitations = Array.from(document.querySelectorAll(".citation-checkbox:checked"))
                    .map(checkbox => checkbox.getAttribute("data-index"));
                showCommentPopup(selectedCitations);
                popup.remove();
            });

            buttonContainer.appendChild(removeSelectedButton);
            popup.appendChild(buttonContainer);
        }

        document.body.appendChild(popup);
    }

   function showCommentPopup(selectedIndices) {
    const commentPopup = document.createElement("div");
    commentPopup.style.position = "fixed";
    commentPopup.style.top = "50%";
    commentPopup.style.left = "50%";
    commentPopup.style.transform = "translate(-50%, -50%)";
    commentPopup.style.backgroundColor = "#2b2b2b";
    commentPopup.style.padding = "20px";
    commentPopup.style.border = "2px solid #3a3a3a";
    commentPopup.style.borderRadius = "12px";
    commentPopup.style.width = "300px";
    commentPopup.style.boxShadow = "0px 8px 16px rgba(0, 0, 0, 0.7)";

    const commentLabel = document.createElement("label");
    commentLabel.style.color = "#ffffff";
    commentLabel.style.fontSize = "14px";
    commentLabel.style.fontWeight = "bold";
    commentLabel.textContent = "Add Comment:";

    const commentInput = document.createElement("textarea");
    commentInput.style.width = "100%";
    commentInput.style.height = "80px";
    commentInput.style.marginTop = "8px";
    commentInput.style.borderRadius = "6px";
    commentInput.style.padding = "8px";
    commentInput.style.backgroundColor = "#404040";
    commentInput.style.color = "#e0e0e0";
    commentInput.style.border = "1px solid #4a4a4a";

    const buttonContainer = document.createElement("div");
    buttonContainer.style.display = "flex";
    buttonContainer.style.justifyContent = "space-between";
    buttonContainer.style.marginTop = "12px";

    // Submit button
    const submitButton = document.createElement("button");
    submitButton.textContent = "Submit";
    submitButton.style.padding = "8px 12px";
    submitButton.style.backgroundColor = "#4CAF50";
    submitButton.style.color = "white";
    submitButton.style.borderRadius = "8px";
    submitButton.style.cursor = "pointer";
    submitButton.addEventListener("click", function() {
    const optionalComment = commentInput.value.trim();
    const defaultComment = "Removed citations (using [[User:GrabUp/Citation Remover|Citation Remover]])";
    const comment = optionalComment ? `"${optionalComment}" | ${defaultComment}` : defaultComment;
        removeCitations(selectedIndices, comment);
        commentPopup.remove();
    });

    // Skip button
    const skipButton = document.createElement("button");
    skipButton.textContent = "Skip";
    skipButton.style.padding = "8px 12px";
    skipButton.style.backgroundColor = "#f44336";
    skipButton.style.color = "white";
    skipButton.style.borderRadius = "8px";
    skipButton.style.cursor = "pointer";
    skipButton.addEventListener("click", function() {
        removeCitations(selectedIndices, "Removed citations (using [[User:GrabUp/Citation Remover|Citation Remover]])");  // No additional comment
        commentPopup.remove();
    });

    // Cancel button
    const cancelButton = document.createElement("button");
    cancelButton.textContent = "Cancel";
    cancelButton.style.padding = "8px 12px";
    cancelButton.style.backgroundColor = "#6c757d";
    cancelButton.style.color = "white";
    cancelButton.style.borderRadius = "8px";
    cancelButton.style.cursor = "pointer";
    cancelButton.addEventListener("click", function() {
        commentPopup.remove();  // Close popup without any action
    });

    buttonContainer.appendChild(submitButton);
    buttonContainer.appendChild(skipButton);
    buttonContainer.appendChild(cancelButton);  // Adding "Cancel" button to the container
    commentPopup.appendChild(commentLabel);
    commentPopup.appendChild(commentInput);
    commentPopup.appendChild(buttonContainer);

    document.body.appendChild(commentPopup);
}

   function removeCitations(indices, comment) {
    api.get({
        action: "query",
        titles: mw.config.get('wgPageName'),
        prop: "revisions",
        rvprop: "content",
        formatversion: "2"
    }).then(function(data) {
        let pageContent = data.query.pages[0].revisions[0].content;
        const citations = extractCitations(pageContent);

        // Collect the original texts of selected citations for deletion
        const citationsToRemove = indices.map(index => citations[index].originalText);

        // Remove citations by matching original text to avoid index shifting
        citationsToRemove.forEach(citationText => {
            pageContent = pageContent.replace(citationText, "");
        });

        return api.postWithToken("csrf", {
            action: "edit",
            title: mw.config.get('wgPageName'),
            text: pageContent,
            summary: comment
        });
    }).then(function(editData) {
        const newRevisionId = editData.edit.newrevid;
        if (newRevisionId) {
            window.location.href = mw.util.getUrl(mw.config.get('wgPageName'), {diff: newRevisionId});
        }
    }).catch(console.error);
}


   function deleteRefTag(content, citation) {
    const refName = citation.refName;
    if (refName) {
        const refTagRegex = new RegExp(
            `<ref\\b[^>]*?name=["']${escapeRegExp(refName)}["'][^>]*?\\/?>|<ref\\b[^>]*?name=["']${escapeRegExp(refName)}["'][^>]*?>.*?<\\/ref>`,
            "gs"
        );
        content = content.replace(refTagRegex, "");
    }

    return content.replace(citation.originalText, "");
}

    function escapeRegExp(string) {
        return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    }
});