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 `${match}`; - }); + 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 `${match}`; - }); + 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 `${match}`; - }); + 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}.`;