Overleaf Toolbar Word Count

Show live word count in the Overleaf PDF toolbar

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey, Greasemonkey of Violentmonkey.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Violentmonkey.

Voor het installeren van scripts heb je een extensie nodig, zoals Tampermonkey of Userscripts.

Voor het installeren van scripts heb je een extensie nodig, zoals {tampermonkey_link:Tampermonkey}.

Voor het installeren van scripts heb je een gebruikersscriptbeheerder nodig.

(Ik heb al een user script manager, laat me het downloaden!)

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een extensie nodig, zoals {stylus_link:Stylus}.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

Voor het installeren van gebruikersstijlen heb je een gebruikersstijlbeheerder nodig.

(Ik heb al een beheerder - laat me doorgaan met de installatie!)

// ==UserScript==
// @name         Overleaf Toolbar Word Count
// @namespace    parnavh.dev
// @version      2026-08-04
// @description  Show live word count in the Overleaf PDF toolbar
// @match        https://www.overleaf.com/project/*
// @grant        none
// @author       parnavh
// @icon         https://www.google.com/s2/favicons?sz=64&domain=overleaf.com
// @license MIT
// ==/UserScript==

(function () {
    'use strict';

    let counter;

    async function updateWordCount() {
        try {
            const res = await fetch(location.pathname + "/wordcount", {
                credentials: "same-origin",
                cache: "no-store"
            });

            if (!res.ok) return;

            const { texcount } = await res.json();

            counter.textContent = `Words: ${texcount.textWords.toLocaleString()}`;
        } catch (e) {
            console.error("Word count failed", e);
        }
    }

    function install() {
        if (document.getElementById("tm-word-count"))
            return false;

        const toolbar = document.querySelector(".toolbar-pdf-left");
        if (!toolbar)
            return false;

        counter = document.createElement("span");
        counter.id = "tm-word-count";
        counter.textContent = "Words: ...";

        counter.style.cssText = `
            font-size:14px;
        `;

        toolbar.appendChild(counter);

        updateWordCount();

        const compileBtn = document.querySelector(".compile-button");

        if (compileBtn) {
            const compileObserver = new MutationObserver(() => {
                if (compileBtn.dataset.olLoading === "false") {
                    updateWordCount();
                }
            });

            compileObserver.observe(compileBtn, {
                attributes: true,
                attributeFilter: ["data-ol-loading"]
            });
        }

        return true;
    }

    // Wait until Overleaf has rendered
    const observer = new MutationObserver(() => {
        if (install()) {
            observer.disconnect();
        }
    });

    observer.observe(document.body, {
        childList: true,
        subtree: true
    });
})();