From e835d74272cf6985a496bd40fc87c9b7bd1f0048 Mon Sep 17 00:00:00 2001
From: liyunze <50455574+liyunze-coding@users.noreply.github.com>
Date: Mon, 3 Aug 2026 15:00:04 +1000
Subject: [PATCH] filer html tags, fixed configs
---
widgets/horizontal/scripts/emotes.js | 54 +++++++++++++++----
widgets/horizontal/scripts/tasklist-view.js | 16 ++++--
widgets/streamer-only/scripts/emotes.js | 54 +++++++++++++++----
.../streamer-only/scripts/tasklist-view.js | 16 ++++--
widgets/vertical/scripts/emotes.js | 54 +++++++++++++++----
widgets/vertical/scripts/tasklist-view.js | 16 ++++--
6 files changed, 168 insertions(+), 42 deletions(-)
diff --git a/widgets/horizontal/scripts/emotes.js b/widgets/horizontal/scripts/emotes.js
index 881f87e..b0d8836 100644
--- a/widgets/horizontal/scripts/emotes.js
+++ b/widgets/horizontal/scripts/emotes.js
@@ -57,18 +57,54 @@ class EmoteManager {
this.#patternSize = this.#emotes.size;
}
- parseText(text) {
- if (!text || !this.#loaded || this.#emotes.size === 0) return text;
+ renderInto(container, text) {
+ container.replaceChildren();
+ if (text == null || text === "") return;
+
+ if (!this.#loaded || this.#emotes.size === 0) {
+ container.textContent = text;
+ return;
+ }
this.#buildPattern();
- if (!this.#pattern) return text;
+ if (!this.#pattern) {
+ container.textContent = text;
+ return;
+ }
- return text.replace(this.#pattern, (match) => {
- const emote = this.#emotes.get(match);
- if (!emote) return match;
- console.log(emote);
- return `
`;
- });
+ const pattern = new RegExp(this.#pattern.source, this.#pattern.flags);
+ const nodes = [];
+ let lastIndex = 0;
+ let match;
+
+ while ((match = pattern.exec(text)) !== null) {
+ if (match.index > lastIndex) {
+ nodes.push(
+ document.createTextNode(text.slice(lastIndex, match.index)),
+ );
+ }
+
+ const name = match[0];
+ const emote = this.#emotes.get(name);
+ if (emote?.url && /^https?:\/\//i.test(emote.url)) {
+ const img = document.createElement("img");
+ img.src = emote.url;
+ img.alt = name;
+ img.title = `${name} (${emote.provider})`;
+ img.className = "emote-img";
+ nodes.push(img);
+ } else {
+ nodes.push(document.createTextNode(name));
+ }
+
+ lastIndex = match.index + name.length;
+ }
+
+ if (lastIndex < text.length) {
+ nodes.push(document.createTextNode(text.slice(lastIndex)));
+ }
+
+ container.replaceChildren(...nodes);
}
async init() {
diff --git a/widgets/horizontal/scripts/tasklist-view.js b/widgets/horizontal/scripts/tasklist-view.js
index 41372f3..ff50539 100644
--- a/widgets/horizontal/scripts/tasklist-view.js
+++ b/widgets/horizontal/scripts/tasklist-view.js
@@ -303,11 +303,17 @@ class TaskList {
// ── dom helpers ────────────────────────────────────
- #parseTaskText(text) {
+ #stripHtml(text) {
+ return String(text ?? "").replace(/<\/?[^>\n]+>/g, "");
+ }
+
+ #setTaskText(el, text) {
+ const safe = this.#stripHtml(text);
if (window.emoteManager && window.emoteManager.loaded) {
- return window.emoteManager.parseText(text);
+ window.emoteManager.renderInto(el, safe);
+ } else {
+ el.textContent = safe;
}
- return text;
}
#createTaskEl(task, index) {
@@ -323,7 +329,7 @@ class TaskList {
const textSpan = document.createElement("span");
textSpan.className = "task-text";
- textSpan.innerHTML = this.#parseTaskText(task.text);
+ this.#setTaskText(textSpan, task.text);
div.replaceChildren(numberSpan, textSpan);
return div;
@@ -378,7 +384,7 @@ class TaskList {
const textEl =
el.querySelector(".task-text") ||
el.querySelector("span:last-child");
- textEl.innerHTML = this.#parseTaskText(task.text);
+ this.#setTaskText(textEl, task.text);
}
el.querySelector(".task-number").textContent = `${i + 1}.`;
diff --git a/widgets/streamer-only/scripts/emotes.js b/widgets/streamer-only/scripts/emotes.js
index 881f87e..b0d8836 100644
--- a/widgets/streamer-only/scripts/emotes.js
+++ b/widgets/streamer-only/scripts/emotes.js
@@ -57,18 +57,54 @@ class EmoteManager {
this.#patternSize = this.#emotes.size;
}
- parseText(text) {
- if (!text || !this.#loaded || this.#emotes.size === 0) return text;
+ renderInto(container, text) {
+ container.replaceChildren();
+ if (text == null || text === "") return;
+
+ if (!this.#loaded || this.#emotes.size === 0) {
+ container.textContent = text;
+ return;
+ }
this.#buildPattern();
- if (!this.#pattern) return text;
+ if (!this.#pattern) {
+ container.textContent = text;
+ return;
+ }
- return text.replace(this.#pattern, (match) => {
- const emote = this.#emotes.get(match);
- if (!emote) return match;
- console.log(emote);
- return `
`;
- });
+ const pattern = new RegExp(this.#pattern.source, this.#pattern.flags);
+ const nodes = [];
+ let lastIndex = 0;
+ let match;
+
+ while ((match = pattern.exec(text)) !== null) {
+ if (match.index > lastIndex) {
+ nodes.push(
+ document.createTextNode(text.slice(lastIndex, match.index)),
+ );
+ }
+
+ const name = match[0];
+ const emote = this.#emotes.get(name);
+ if (emote?.url && /^https?:\/\//i.test(emote.url)) {
+ const img = document.createElement("img");
+ img.src = emote.url;
+ img.alt = name;
+ img.title = `${name} (${emote.provider})`;
+ img.className = "emote-img";
+ nodes.push(img);
+ } else {
+ nodes.push(document.createTextNode(name));
+ }
+
+ lastIndex = match.index + name.length;
+ }
+
+ if (lastIndex < text.length) {
+ nodes.push(document.createTextNode(text.slice(lastIndex)));
+ }
+
+ container.replaceChildren(...nodes);
}
async init() {
diff --git a/widgets/streamer-only/scripts/tasklist-view.js b/widgets/streamer-only/scripts/tasklist-view.js
index 68e67b8..80e2aed 100644
--- a/widgets/streamer-only/scripts/tasklist-view.js
+++ b/widgets/streamer-only/scripts/tasklist-view.js
@@ -279,11 +279,17 @@ class TaskList {
// ── dom helpers ────────────────────────────────────
- #parseTaskText(text) {
+ #stripHtml(text) {
+ return String(text ?? "").replace(/<\/?[^>\n]+>/g, "");
+ }
+
+ #setTaskText(el, text) {
+ const safe = this.#stripHtml(text);
if (window.emoteManager && window.emoteManager.loaded) {
- return window.emoteManager.parseText(text);
+ window.emoteManager.renderInto(el, safe);
+ } else {
+ el.textContent = safe;
}
- return text;
}
#createTaskEl(task, index) {
@@ -299,7 +305,7 @@ class TaskList {
const textSpan = document.createElement("span");
textSpan.className = "task-text";
- textSpan.innerHTML = this.#parseTaskText(task.text);
+ this.#setTaskText(textSpan, task.text);
div.replaceChildren(numberSpan, textSpan);
return div;
@@ -354,7 +360,7 @@ class TaskList {
const textEl =
el.querySelector(".task-text") ||
el.querySelector("span:last-child");
- textEl.innerHTML = this.#parseTaskText(task.text);
+ this.#setTaskText(textEl, task.text);
}
el.querySelector(".task-number").textContent = `${i + 1}.`;
diff --git a/widgets/vertical/scripts/emotes.js b/widgets/vertical/scripts/emotes.js
index 881f87e..b0d8836 100644
--- a/widgets/vertical/scripts/emotes.js
+++ b/widgets/vertical/scripts/emotes.js
@@ -57,18 +57,54 @@ class EmoteManager {
this.#patternSize = this.#emotes.size;
}
- parseText(text) {
- if (!text || !this.#loaded || this.#emotes.size === 0) return text;
+ renderInto(container, text) {
+ container.replaceChildren();
+ if (text == null || text === "") return;
+
+ if (!this.#loaded || this.#emotes.size === 0) {
+ container.textContent = text;
+ return;
+ }
this.#buildPattern();
- if (!this.#pattern) return text;
+ if (!this.#pattern) {
+ container.textContent = text;
+ return;
+ }
- return text.replace(this.#pattern, (match) => {
- const emote = this.#emotes.get(match);
- if (!emote) return match;
- console.log(emote);
- return `
`;
- });
+ const pattern = new RegExp(this.#pattern.source, this.#pattern.flags);
+ const nodes = [];
+ let lastIndex = 0;
+ let match;
+
+ while ((match = pattern.exec(text)) !== null) {
+ if (match.index > lastIndex) {
+ nodes.push(
+ document.createTextNode(text.slice(lastIndex, match.index)),
+ );
+ }
+
+ const name = match[0];
+ const emote = this.#emotes.get(name);
+ if (emote?.url && /^https?:\/\//i.test(emote.url)) {
+ const img = document.createElement("img");
+ img.src = emote.url;
+ img.alt = name;
+ img.title = `${name} (${emote.provider})`;
+ img.className = "emote-img";
+ nodes.push(img);
+ } else {
+ nodes.push(document.createTextNode(name));
+ }
+
+ lastIndex = match.index + name.length;
+ }
+
+ if (lastIndex < text.length) {
+ nodes.push(document.createTextNode(text.slice(lastIndex)));
+ }
+
+ container.replaceChildren(...nodes);
}
async init() {
diff --git a/widgets/vertical/scripts/tasklist-view.js b/widgets/vertical/scripts/tasklist-view.js
index 70ab5d5..37519c9 100644
--- a/widgets/vertical/scripts/tasklist-view.js
+++ b/widgets/vertical/scripts/tasklist-view.js
@@ -302,11 +302,17 @@ class TaskList {
// ── dom helpers ────────────────────────────────────
- #parseTaskText(text) {
+ #stripHtml(text) {
+ return String(text ?? "").replace(/<\/?[^>\n]+>/g, "");
+ }
+
+ #setTaskText(el, text) {
+ const safe = this.#stripHtml(text);
if (window.emoteManager && window.emoteManager.loaded) {
- return window.emoteManager.parseText(text);
+ window.emoteManager.renderInto(el, safe);
+ } else {
+ el.textContent = safe;
}
- return text;
}
#createTaskEl(task, index) {
@@ -322,7 +328,7 @@ class TaskList {
const textSpan = document.createElement("span");
textSpan.className = "task-text";
- textSpan.innerHTML = this.#parseTaskText(task.text);
+ this.#setTaskText(textSpan, task.text);
div.replaceChildren(numberSpan, textSpan);
return div;
@@ -377,7 +383,7 @@ class TaskList {
const textEl =
el.querySelector(".task-text") ||
el.querySelector("span:last-child");
- textEl.innerHTML = this.#parseTaskText(task.text);
+ this.#setTaskText(textEl, task.text);
}
el.querySelector(".task-number").textContent = `${i + 1}.`;