Ir al contenido

Texto seguro de los espectadores

Todo lo que escribe un espectador (su nombre, su mensaje, el texto de un cheer) lo controla otra persona. Si lo pintas como HTML, alguien puede mandar <img src=x onerror=…> y acabar dentro de tu overlay. Por eso el validador no deja usar innerHTML (js_forbidden_html) y, en la prueba de ejecución, lanza un mensaje con HTML y comprueba que no se convierte en elementos (runtime_injection).

// Mal: el HTML del mensaje se interpreta
box.innerHTML = `<b>${user}</b>: ${message}`;
script.js
const app = document.querySelector("#app");
Widget.on("Twitch.ChatMessage", ({ user, message }) => {
const line = document.createElement("div");
const name = document.createElement("b");
Widget.dom.text(name, user);
const text = document.createElement("span");
Widget.dom.text(text, message);
line.append(name, ": ", text);
app.replaceChildren(line);
});
manifest.json
{
"events": ["Twitch.ChatMessage"],
"strings": { "es": {}, "en": {} },
"menu": { "sections": [] }
}
index.html
<div id="app"></div>
  • createElement y append: construyes la estructura tú, elemento a elemento. Lo que añades como texto nunca es HTML.
  • Widget.dom.text: pone un valor con textContent. Úsalo para nombres, cantidades y cualquier cosa que venga del evento.
  • Widget.dom.renderMessage: para un mensaje con emotes. Recibe message.parts y devuelve un fragmento con los emotes como imágenes y el resto como texto.
  • Widget.dom.image: una imagen solo si su URL es de una CDN permitida (emotes, insignias, cheers); si no, devuelve null. Comprueba el resultado antes de añadirlo.

Los textos fijos del widget («Gracias por el follow») van en strings y se leen con Widget.t. Si mezclas variables, pásalas como segundo argumento: Widget.t("follow", { name: user }). El valor se sustituye como texto, y el resultado se pinta con Widget.dom.text.