From 7374edc0773988ac3de4d0480a1005d5d1c8cd6d Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Fri, 13 Nov 2026 19:56:19 +0000 Subject: Take the giant Google badge out of the reader "Remove giant Google icon", reported on a West Hawaii Today article. It is the "Add as a preferred source on Google" badge that sits beside the byline. Giant because the page caps it at 120px with its own stylesheet and the reader drops the page's CSS, so a small badge on the site becomes a full-width image above the first paragraph. Matched on the link's address rather than the class, and that is forced rather than preferred: running the vendored Readability.js over the real page shows the wrapper's preferred_source_badge class does not survive extraction at all, so a class rule would match nothing. The anchor does survive, and its address is Google's own and identical for every publisher in the programme -- where the badge's image filename sits under this newspaper's theme directory and is not. So the address is both the only signal left and the one that generalises. A link with words in it is never touched. An article may discuss the programme and link to it in a sentence, and that sentence is the author's. Both cleaners now run from one entry point. There are two places a body is cleaned -- a fresh extraction on the way out, a cached one on the way back in -- and a cached article is cleaned in place rather than discarded, so a cleaner wired into only the fresh path would leave every already-read article carrying litter nothing would ever remove. Peter's report says the article was cached, which is exactly that case. Pinned against the real thing: the reported article, put through the real extractor, loses the badge and keeps its text and byline. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B --- .../feedreader/readability/ArticleLitterTest.kt | 47 ++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 app/src/test/java/org/terst/feedreader/readability/ArticleLitterTest.kt (limited to 'app/src/test/java/org/terst/feedreader/readability/ArticleLitterTest.kt') diff --git a/app/src/test/java/org/terst/feedreader/readability/ArticleLitterTest.kt b/app/src/test/java/org/terst/feedreader/readability/ArticleLitterTest.kt new file mode 100644 index 0000000..121783b --- /dev/null +++ b/app/src/test/java/org/terst/feedreader/readability/ArticleLitterTest.kt @@ -0,0 +1,47 @@ +package org.terst.feedreader.readability + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test + +/** + * The single entry point both cleaning sites call. + * + * The thing worth testing is that it applies *every* cleaner, because the failure it exists to + * prevent is a cleaner that only runs on one of the two paths. + */ +class ArticleLitterTest { + + private val recirculationWidget = + """
""" + + """

Trending

""" + + private val preferredSourceBadge = + """

""" + + """

""" + + @Test + fun `removes both kinds of litter from one body`() { + val html = "$preferredSourceBadge

Real sentence.

$recirculationWidget" + + val cleaned = ArticleLitter.strip(html)!! + + assertFalse("badge survived: $cleaned", cleaned.contains("preferences/source")) + assertFalse("widget survived: $cleaned", cleaned.contains("Trending")) + assertTrue(cleaned.contains("Real sentence.")) + } + + @Test + fun `leaves a clean article untouched`() { + val html = "

Nothing to clean.

" + + assertEquals(html, ArticleLitter.strip(html)) + } + + @Test + fun `copes with nothing`() { + assertEquals(null, ArticleLitter.strip(null)) + } +} -- cgit v1.2.3