Gutencount

Accurate word counter for Gutenberg texts

当前为 2023-04-11 提交的版本,查看 最新版本

// ==UserScript==
// @name         Gutencount
// @namespace    https://vox.quartertone.net/
// @version      1.1
// @description  Accurate word counter for Gutenberg texts
// @author       quartertone
// @match        *://*.gutenberg.org/*
// @grant        none
// @license      gpl-3.0
// ==/UserScript==

(function() {
    'use strict';

  let loc = document.location.toString();
  let sel = window.getSelection() + "";
  let monkey = true; //tampermonkey flag
  function wx(t, x, r = "") {
    // match gutenberg ebook text between START and END markers
    // accuracy of word count depends on presence of extraneous text such as "transcriber's notes", book summaries, page numbers etc
    return wc(t.match(/(?<=\*{3} START.*?\*{3}).*(?=\*{3} END.*?\*{3})/s)[0].trim(), x, r);
  }
  function wc(t, x, r = "") {
    // trim whitespace, count non-space things and place in alert box
    // TODO: need to include — (long hyhen)
    // let w = t.trim().match(/[\*\S]+/g).length;
    // let w = t.trim().match(/[^\s\*—-]+/g).length;
    let w = t.trim().split(/--|[\s\*—]+/).length;
    if (r) return w; // return the word count as a number if requested; this skips the alert
    // alert(w + "\ words,\ " + t.length + "\ chars\nin\ " + x);
    let alrt = w + "\ words,\ " + t.length + "\ chars\nin\ " + x;
    if (monkey) {cornerbox(alrt);} else {alert(alrt);}
  }
  function fwx(l, a) {
    // fetch link => get text from result => send text to wx function
    fetch(l).then((r) => r.text()).then((t) => {
      let c = wx(t, "ebook", a);
      if (a) {
        a.innerHTML += "wc: " + c;
      }
    }).catch((e) => { }); // alert(e));
  }
  if (sel.length > 0) { // selection
    wc(sel, "selection");
  } else if (loc.match(/gutenberg.org\/(files|cache\/epub)\/\d+/)) {
    // gutenberg text
    wx(document.body.innerText, "ebook");
  } else if (loc.match(/gutenberg.org\/ebooks\/(\d+)/)) {
    // gutenberg main ebook page
    fwx(loc + ".txt.utf-8", document.querySelector("#cover"));
  } else if (loc.match(/gutenberg.org\/ebooks\/(subject|search)/)) {
    // gutenberg search or subject page
    for (const a of document.querySelectorAll(".booklink>a>span:nth-child(2)")) {
      // append word counts to each book section
      // second CHILD of the <a> is the "content" span
      fwx(a.parentElement.href + ".txt.utf-8", a);
    }
  } else { // general webpage
    wc(document.body.innerText, "webpage");
  }

  function cornerbox(wcount) {
    console.log(wcount);
    let xcount = document.getElementById("xcount") || document.createElement("div");
    xcount.id = "xcount";
    xcount.style = "position:fixed;top:0;right:0;width:10em;height:2em;background:#333c;color:#fff;z-index:10000;padding:0.5em;text-align:right;";
    xcount.innerHTML = "";
    xcount.ondblclick = function () {
      this.remove();
    };
    document.body.appendChild(xcount);
    xcount.innerHTML = wcount;
  }

})();