DavidPurkiss

Este script que estoy poniendo aquí lo hice con ayuda de ChatGPT para poner fechas, conteo de palabras, minuto de lectura y hace cuánto se publicó el contenido.

Después, hay dos pequeñas líneas que son para especificar en páginas hace cuánto se publicó. Hay otra línea de código que es para quitar esa metainformación de algún post o página donde no lo quieras poner.

(Ojo falta el primer simbolo de script)

script> document.addEventListener("DOMContentLoaded", () => {

/* ===================================================== CONFIGURACIÓN DE EXCLUSIONES ===================================================== */

// 1️⃣ Excluir por URL (ej. /blog/) const excludedPaths = [ "/blog/" ];

const currentPath = window.location.pathname; if (excludedPaths.some(p => currentPath.startsWith℗)) { return; // ⛔ No ejecutar nada }

// 2️⃣ Excluir por meta tag // const disabledByMeta = document.querySelector( 'meta[name="post-stats"][content="off"]' ); if (disabledByMeta) return;

/* ===================================================== LOCALIZAR CONTENEDOR PRINCIPAL ===================================================== */ function findContainer() { const selectors = [ "article", "main article", ".post", ".entry-content", "#post", ".article", "main", "body" ]; for (const s of selectors) { const el = document.querySelector(s); if (el) return el; } return null; }

/* ===================================================== PARSEO DE FECHAS ===================================================== */ function parseDateString(str) { if (!str) return null;

const clean = String(str) .trim() .replace(/\s+/g, " ") .replace(/,\s*/g, ", ");

let d = new Date(clean); if (!isNaN(d)) return d;

d = new Date(clean.replace(/,/, "")); if (!isNaN(d)) return d;

const m = clean.match(/(\d{4})-/-//); if (m) { return new Date( ${m[1]}-${m[2].padStart(2,"0")}-${m[3].padStart(2,"0")} ); }

return null; }

/* ===================================================== TEXTO VISIBLE Y CONTEO ===================================================== */ function getVisibleText(el) { const clone = el.cloneNode(true); clone.querySelectorAll( "script,style,noscript,iframe,svg,img,picture,aside,.ad,.ads,.share,.post-stats" ).forEach(n => n.remove());

return (clone.textContent || "") .replace(/\s+/g, " ") .trim(); }

function countWords(text) { return text ? (text.match(/\S+/g) || []).length : 0; }

/* ===================================================== TIEMPO RELATIVO ===================================================== */ function timeAgo(from, now = new Date()) { if (!from || isNaN(from)) return null;

const s = Math.floor((now - from) / 1000); if (s < 15) return "hace unos segundos"; if (s < 60) return hace ${s} segundos;

const m = Math.floor(s / 60); if (m < 60) return m === 1 ? "hace 1 minuto" : hace ${m} minutos;

const h = Math.floor(m / 60); if (h < 24) return h === 1 ? "hace 1 hora" : hace ${h} horas;

const d = Math.floor(h / 24); if (d < 7) return d === 1 ? "hace 1 día" : hace ${d} días;

const w = Math.floor(d / 7); if (w < 5) return w === 1 ? "hace 1 semana" : hace ${w} semanas;

const mo = Math.floor(d / 30); if (mo < 12) return mo === 1 ? "hace 1 mes" : hace ${mo} meses;

const y = Math.floor(d / 365); return y === 1 ? "hace 1 año" : hace ${y} años; }

/* ===================================================== INIT ===================================================== */ (function init() {

const container = findContainer(); if (!container) return;

/* --- palabras / lectura --- */ const text = getVisibleText(container); const words = countWords(text); const minutes = Math.max(1, Math.ceil(words / 200));

/* --- fecha --- */ let pubDate = null;

const timeEl = document.querySelector("time"); if (timeEl) { pubDate = parseDateString( timeEl.getAttribute("datetime") || timeEl.textContent ); }

if (!pubDate) { const metaDate = document.querySelector('meta[name="date"]'); if (metaDate) pubDate = parseDateString(metaDate.content); }

if (!words && !pubDate) return;

/* --- bloque meta --- */ const meta = document.createElement("div"); meta.className = "post-stats"; Object.assign(meta.style, { fontSize: "0.95em", color: "#444", margin: "1.6em auto", padding: "0.6em 0", borderTop: "1px solid #ccc", borderBottom: "1px solid #ccc", textAlign: "center", fontStyle: "italic" });

const lines = [];

if (words > 0) { lines.push( 📖 ${words.toLocaleString("es-MX")} palabras · ~${minutes} min de lectura ); }

if (pubDate) { const dateFmt = pubDate.toLocaleDateString("es-MX", { year: "numeric", month: "long", day: "numeric" }); const ago = timeAgo(pubDate); lines.push(Publicado: ${dateFmt}${ago ? · ${ago} : ""}); }

meta.innerHTML = lines.join("
");

/* --- insertar debajo del título --- */ const heading = container.querySelector("h1,h2,header"); if (heading && heading.nextSibling) { heading.parentNode.insertBefore(meta, heading.nextSibling); } else { container.insertBefore(meta, container.firstChild); }

/* --- barra de progreso --- */ if (!document.getElementById("__read_progress")) { const bar = document.createElement("div"); bar.id = "__read_progress"; Object.assign(bar.style, { position: "fixed", top: 0, left: 0, height: "4px", width: "0%", background: "#ff6347", zIndex: 100000, transition: "width .12s linear" });

document.documentElement.appendChild(bar);

window.addEventListener("scroll", () => { const st = window.scrollY || document.documentElement.scrollTop; const dh = Math.max( document.documentElement.scrollHeight, document.body.scrollHeight ); const wh = window.innerHeight; const pct = (st / (dh - wh)) * 100; bar.style.width = Math.max(0, Math.min(100, pct)) + "%"; }, { passive: true }); }

/* --- botón subir --- */ if (!document.getElementById("__go_top")) { const btn = document.createElement("button"); btn.id = "__go_top"; btn.textContent = "↑"; Object.assign(btn.style, { position: "fixed", right: "18px", bottom: "22px", padding: "10px 12px", borderRadius: "8px", border: "none", background: "#ff6347", color: "#fff", cursor: "pointer", zIndex: 100000, opacity: "0", transform: "translateY(8px)", transition: "opacity .28s, transform .18s" });

btn.onclick = () => window.scrollTo({ top: 0, behavior: "smooth" });

window.addEventListener("scroll", () => { if (window.scrollY > 240) { btn.style.opacity = "1"; btn.style.transform = "translateY(0)"; } else { btn.style.opacity = "0"; btn.style.transform = "translateY(8px)"; } }, { passive: true });

document.body.appendChild(btn); }

})();

}); ´´´

1️⃣ LÍNEA PARA DEFINIR LA FECHA (POST o PÁGINA)

Usa UNA de estas (la más correcta es la primera):

👉 Esa línea es la que el script usa para:

saber que es un post

calcular el “hace X tiempo”

Puedes ponerla también en una página si quieres que se comporte como post.

2️⃣ LÍNEA PARA DESACTIVAR EL SCRIPT EN UNA PÁGINA O POST

👉 Con esa sola línea:

no aparece el conteo

no aparece el “hace X tiempo”

no importa si es post o página