diff --git a/src/content/definition-engine.ts b/src/content/definition-engine.ts
index 7f725ff..95aef2f 100644
--- a/src/content/definition-engine.ts
+++ b/src/content/definition-engine.ts
@@ -75,8 +75,12 @@ export class DefinitionEngine {
private extractText(post: Element): string {
for (const selector of this.definition.post.textSelectors) {
- const content = post.matches(selector) ? post : post.querySelector(selector);
- if (content) return visibleText(content, this.definition.post.excludedSelectors ?? []);
+ const matches = Array.from(post.querySelectorAll(selector));
+ const contents = post.matches(selector) ? [post, ...matches] : matches;
+ for (const content of contents) {
+ const text = visibleText(content, this.definition.post.excludedSelectors ?? []);
+ if (text) return text;
+ }
}
return "";
}
diff --git a/src/content/definitions/default.json b/src/content/definitions/default.json
index f5af089..6a235ab 100644
--- a/src/content/definitions/default.json
+++ b/src/content/definitions/default.json
@@ -26,11 +26,11 @@
"https://threads.net/*",
"https://www.threads.net/*"
],
- "requiredSelectors": ["[data-pressable-container=\"true\"], [role=\"article\"], article"],
+ "requiredSelectors": ["[role=\"article\"], article"],
"post": {
- "rootSelectors": ["[data-pressable-container=\"true\"]", "[role=\"article\"]", "article"],
- "textSelectors": ["span[dir=\"auto\"]:not(a span):not(time span):not([role=\"button\"] span)"],
- "excludedSelectors": ["button", "[role=\"button\"]", "time", "svg"],
+ "rootSelectors": ["[role=\"article\"]", "article"],
+ "textSelectors": ["span[dir=\"auto\"]"],
+ "excludedSelectors": ["button", "[role=\"button\"]", "time", "svg", "a span", "time span", "[role=\"button\"] span"],
"permalinkSelectors": ["a[href*=\"/post/\"]"]
}
}
diff --git a/src/options/main.ts b/src/options/main.ts
index a07e4e5..f290e42 100644
--- a/src/options/main.ts
+++ b/src/options/main.ts
@@ -46,6 +46,7 @@ addSubscriptionButton?.addEventListener("click", async () => {
refreshSubscriptionsButton?.addEventListener("click", async () => {
try {
const response = await chrome.runtime.sendMessage({ type: "REFRESH_SUBSCRIPTIONS" });
+ if (!response) throw new Error("The background page did not respond. Reload the extension and try again.");
if (response?.error) throw new Error(response.error);
currentSettings = response.settings;
renderSubscriptions(currentSettings);
diff --git a/tests/definition-engine.test.ts b/tests/definition-engine.test.ts
index b096446..128e966 100644
--- a/tests/definition-engine.test.ts
+++ b/tests/definition-engine.test.ts
@@ -61,6 +61,21 @@ describe("DefinitionEngine", () => {
expect(observed).toContain("content warning revealed text");
});
+ it("discovers Threads posts appended after observation starts", async () => {
+ document.body.innerHTML = '