MediaWiki:Gadget-Wordcount.js

From wikishia

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
//<nowiki>
function getWordCount(html) {
    const text = html.innerHTML.replace(/(<([^>]+)>)/ig, "").trim();
    const words = text.match(/[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FFF\uF900-\uFAFF\u3400-\u4DBF]|\S+/g);
    return words ? words.length : 0;
}

function getContentDiv() {
    return mw.config.get('wgAction') === 'edit' 
        ? document.getElementById('wikiPreview') 
        : document.getElementById('mw-content-text');
}

function isExcludedNode(node) {
    // Check if the node is part of an excluded template or reference section
    return node.closest(".toccolours, .textQuran, .references, .reflist, .refbegin") !== null;
}

function isValidNode(node) {
    // Check if the node is valid for word counting
    const bodyContent = getContentDiv();
    if (!bodyContent) return false;

    // Check parent exclusions
    let curNode = node;
    while (curNode && curNode !== bodyContent) {
        if (curNode.classList.contains("infobox") || 
            curNode.classList.contains("metadata") || 
            curNode.classList.contains("navbox") || 
            curNode.classList.contains("toc")) {
            return false;
        }
        curNode = curNode.parentElement;
    }

    // Exclude specific templates
    return !isExcludedNode(node);
}

function applyStyles(node, style) {
    node.style.cssText = style;
}

function toggleWordCount() {
    const bodyContent = getContentDiv();
    if (!bodyContent) {
        alert("محتوا یافت نشد!");
        return;
    }

    const existingStats = document.getElementById("word-count-stats");
    if (existingStats) {
        existingStats.remove();
        const header = document.getElementById("word-count-header");
        if (header) header.remove();
    } else {
        generateStatistics(bodyContent);
    }
}

function generateStatistics(bodyContent) {
    // Create UI elements for statistics
    const output = document.createElement("div");
    output.id = "word-count-stats";
    output.innerHTML = `
        <div id="word-count-header"><b>شمارشگر کلمات</b></div>
        <table class="word-count-table">
            <tr><td>محتوای اصلی:</td><td id="main-body-stat"></td></tr>
            <tr><td>ارجاعات:</td><td id="ref-stat"></td></tr>
            <tr><td>جمع کل:</td><td id="total-stat"></td></tr>
        </table>`;
    bodyContent.prepend(output);

    let mainBodyCount = 0;
    let refCount = 0;

    // Process paragraphs
    const paragraphs = Array.from(bodyContent.getElementsByTagName("p"));
    paragraphs.forEach(para => {
        if (isValidNode(para)) {
            const count = getWordCount(para);
            if (count > 0) {
                mainBodyCount += count;
                applyStyles(para, "background-color: #ffe9a0; border-left: 5px solid #ffd700; padding-left: 5px;");
            }
        }
    });

    // Process lists
    const listItems = Array.from(bodyContent.querySelectorAll("li, dd"));
    listItems.forEach(item => {
        if (isValidNode(item)) {
            const count = getWordCount(item);
            if (count > 0) {
                mainBodyCount += count;
                applyStyles(item, "background-color: #d5f4e6; border-left: 5px solid #88d8b0; padding-left: 5px;");
            }
        } else if (isExcludedNode(item)) {
            refCount += getWordCount(item);
            applyStyles(item, "background-color: #cfe8fc; border-left: 5px solid #70b5f9; padding-left: 5px;"); // Updated color
        }
    });

    // Process headings (h2 to h6)
    const headings = Array.from(bodyContent.querySelectorAll("h2, h3, h4, h5, h6"));
    headings.forEach(heading => {
        if (isValidNode(heading)) {
            const count = getWordCount(heading);
            if (count > 0) {
                mainBodyCount += count;
                applyStyles(heading, "background-color: #e3daff; border-left: 5px solid #7a67f9; padding-left: 5px;");
            }
        }
    });

    document.getElementById("main-body-stat").innerText = convertToPersian(mainBodyCount);
    document.getElementById("ref-stat").innerText = convertToPersian(refCount);
    document.getElementById("total-stat").innerText = convertToPersian(mainBodyCount + refCount);
}

function convertToPersian(number) {
    return number.toString().replace(/\d/g, digit => "۰۱۲۳۴۵۶۷۸۹"[digit]);
}

jQuery(function () {
    mw.loader.using(['mediawiki.util'], function () {
        const validActions = ['edit', 'view', 'submit', 'historysubmit', 'purge'];
        if (validActions.includes(mw.config.get('wgAction'))) {
            const link = mw.util.addPortletLink('p-tb', '#', 'شمارشگر کلمات', 't-word-count', 'محاسبه تعداد کلمات');
            jQuery(link).click(toggleWordCount);
        }
    });
});
//</nowiki>