diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-07-22 20:46:48 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-07-22 20:46:48 +0000 |
| commit | 8e06fc84c0b540f8ba87afa19d4c08eab7af80d9 (patch) | |
| tree | 46a76a625c4265b14514dfc9d3575e8c5546f1fd /app/src/main/java/org | |
| parent | 34b663c6e75a2c360de154418dafb8f616b546a1 (diff) | |
Resolve lazy-loaded images/media before running Readability
Many sites lazy-load media via JS: the real URL sits in a data-src/
data-srcset attribute and only gets copied into src/srcset once the
site's own script runs -- which never happens in the reader WebView (JS
is off by design, so articles can't run arbitrary third-party scripts).
Left alone this showed either a placeholder/category icon stretched to
fill the article width (reported live with a screenshot: a giant flask
icon in place of the real photo on an Ars Technica article), or nothing
but alt text (reported for NYT articles' images and videos).
Before either Readability pass, walk <img>/<source> elements and copy
common lazy-load attributes (data-src, data-original, data-lazy-src,
data-srcset) into src/srcset, falling back to the first srcset candidate
if src is still empty. Also strip width/height attributes on images --
they're sized for the site's real photo, not whatever was in the
unresolved src, so our own max-width:100%/height:auto sizing now takes
over based on the (correctly resolved) image's actual dimensions.
Verified live: the Ars Technica article that previously showed the
stretched flask icon now renders clean, with no image where the broken
one used to appear and the full real article text intact.
Diffstat (limited to 'app/src/main/java/org')
| -rw-r--r-- | app/src/main/java/org/terst/feedreader/readability/ReaderExtractor.kt | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/app/src/main/java/org/terst/feedreader/readability/ReaderExtractor.kt b/app/src/main/java/org/terst/feedreader/readability/ReaderExtractor.kt index 7e8e10c..82300ac 100644 --- a/app/src/main/java/org/terst/feedreader/readability/ReaderExtractor.kt +++ b/app/src/main/java/org/terst/feedreader/readability/ReaderExtractor.kt @@ -74,6 +74,44 @@ object ReaderExtractor { return (article && article.textContent) ? article.textContent.trim().length : 0; } + // Many sites lazy-load media via JS: the real URL sits in a + // data-src/data-srcset attribute and only gets copied into + // src/srcset once the site's own script runs -- which never + // happens here (JS is off in the reader WebView by design, so + // articles can't run arbitrary third-party scripts). Left alone + // this shows either a tiny placeholder/category icon stretched to + // fill the article width (the site's width/height attributes, + // sized for the real photo, still apply to whatever's in src), or + // nothing but the img's alt text if src is empty. Resolve these + // before Readability runs so it captures real media, not the + // unresolved lazy attribute. + var lazyAttrs = ['data-src', 'data-original', 'data-lazy-src']; + var imgs = document.querySelectorAll('img'); + for (var i = 0; i < imgs.length; i++) { + var img = imgs[i]; + for (var j = 0; j < lazyAttrs.length; j++) { + var lazySrc = img.getAttribute(lazyAttrs[j]); + if (lazySrc) { img.setAttribute('src', lazySrc); break; } + } + var lazySrcset = img.getAttribute('data-srcset'); + if (lazySrcset) img.setAttribute('srcset', lazySrcset); + if (!img.getAttribute('src') && img.getAttribute('srcset')) { + var first = img.getAttribute('srcset').split(',')[0].trim().split(/\s+/)[0]; + if (first) img.setAttribute('src', first); + } + // Drop width/height attributes now that src may point at a + // differently-sized image than whatever they were set for -- + // our own stylesheet's max-width:100%/height:auto sizes + // correctly from the (now-resolved) image's real dimensions. + img.removeAttribute('width'); + img.removeAttribute('height'); + } + var sources = document.querySelectorAll('source'); + for (var i = 0; i < sources.length; i++) { + var lazySrcset = sources[i].getAttribute('data-srcset') || sources[i].getAttribute('data-src'); + if (lazySrcset) sources[i].setAttribute('srcset', lazySrcset); + } + // Readability's default hidden-element skip (treating display:none / // visibility:hidden nodes as boilerplate) is correct for the vast // majority of sites -- it's what keeps collapsed nav/footer/sidebar |
