Safe viewer text
Everything a viewer writes (their name, their message, a cheer’s text) is controlled by someone else. If you draw it
as HTML, someone can send <img src=x onerror=…> and end up inside your overlay. That is why the validator does not allow innerHTML
(js_forbidden_html) and, in the run test, it sends a message with HTML and
checks that it does not turn into elements (runtime_injection).
What not to do
Section titled “What not to do”// Wrong: the message HTML gets interpretedbox.innerHTML = `<b>${user}</b>: ${message}`;What to do
Section titled “What to do”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);});{ "events": ["Twitch.ChatMessage"], "strings": { "es": {}, "en": {} }, "menu": { "sections": [] }}<div id="app"></div>The four tools
Section titled “The four tools”createElementandappend: you build the structure yourself, element by element. What you add as text is never HTML.Widget.dom.text: sets a value withtextContent. Use it for names, amounts and anything that comes from the event.Widget.dom.renderMessage: for a message with emotes. It takesmessage.partsand returns a fragment with emotes as images and the rest as text.Widget.dom.image: an image only if its URL is from an allowed CDN (emotes, badges, cheers); otherwise it returnsnull. Check the result before adding it.
Your own texts go in strings
Section titled “Your own texts go in strings”The widget’s fixed texts (“Thanks for the follow”) go in strings and are read with Widget.t. If you mix in variables, pass them as the
second argument: Widget.t("follow", { name: user }). The value is substituted as text, and the result is drawn with Widget.dom.text.