From 6eb94f1e1397ae97ed9a0e78d0edc2d04b0915a6 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Jun 2020 11:58:59 +0300 Subject: [PATCH] better support for image srcset attributes as discussed in https://community.tt-rss.org/t/problem-with-img-srcset/3519 --- classes/diskcache.php | 13 +++++-------- classes/rssutils.php | 41 ++++++++++++++++++++++++++++++++++------- include/functions.php | 14 ++++---------- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/classes/diskcache.php b/classes/diskcache.php index be1aea97f..68829b8e3 100644 --- a/classes/diskcache.php +++ b/classes/diskcache.php @@ -314,22 +314,19 @@ class DiskCache { } if ($entry->hasAttribute("srcset")) { - $tokens = explode(",", $entry->getAttribute('srcset')); + $matches = RSSUtils::decode_srcset($entry->getAttribute('srcset')); - for ($i = 0; $i < count($tokens); $i++) { - $token = trim($tokens[$i]); - - list ($url, $width) = explode(" ", $token, 2); - $cached_filename = sha1($url); + for ($i = 0; $i < count($matches); $i++) { + $cached_filename = sha1($matches[$i]["url"]); if ($cache->exists($cached_filename)) { - $tokens[$i] = $cache->getUrl($cached_filename) . " " . $width; + $matches[$i]["url"] = $cache->getUrl($cached_filename); $need_saving = true; } } - $entry->setAttribute("srcset", implode(", ", $tokens)); + $entry->setAttribute("srcset", RSSUtils::encode_srcset($matches)); } } diff --git a/classes/rssutils.php b/classes/rssutils.php index dede50ba0..61763928d 100755 --- a/classes/rssutils.php +++ b/classes/rssutils.php @@ -1196,6 +1196,7 @@ class RSSUtils { return true; } + /* TODO: move to DiskCache? */ static function cache_enclosures($enclosures, $site_url) { $cache = new DiskCache("images"); @@ -1231,6 +1232,7 @@ class RSSUtils { } } + /* TODO: move to DiskCache? */ static function cache_media_url($cache, $url, $site_url) { $url = rewrite_relative_url($site_url, $url); $local_filename = sha1($url); @@ -1257,6 +1259,7 @@ class RSSUtils { } } + /* TODO: move to DiskCache? */ static function cache_media($html, $site_url) { $cache = new DiskCache("images"); @@ -1275,14 +1278,10 @@ class RSSUtils { } if ($entry->hasAttribute("srcset")) { - $tokens = explode(",", $entry->getAttribute('srcset')); + $matches = RSSUtils::decode_srcset($entry->getAttribute('srcset')); - for ($i = 0; $i < count($tokens); $i++) { - $token = trim($tokens[$i]); - - list ($url, $width) = explode(" ", $token, 2); - - RSSUtils::cache_media_url($cache, $url, $site_url); + for ($i = 0; $i < count($matches); $i++) { + RSSUtils::cache_media_url($cache, $matches[$i]["url"], $site_url); } } } @@ -1738,4 +1737,32 @@ class RSSUtils { return $favicon_url; } + // https://community.tt-rss.org/t/problem-with-img-srcset/3519 + static function decode_srcset($srcset) { + $matches = []; + + preg_match_all( + '/(?:\A|,)\s*(?P(?!,)\S+(?\s\d+w|\s\d+(?:\.\d+)?(?:[eE][+-]?\d+)?x|)\s*(?=,|\Z)/', + $srcset, $matches, PREG_SET_ORDER + ); + + foreach ($matches as $m) { + array_push($matches, [ + "url" => trim($m["url"]), + "size" => trim($m["size"]) + ]); + } + + return $matches; + } + + static function encode_srcset($matches) { + $tokens = []; + + foreach ($matches as $m) { + array_push($tokens, trim($m["url"]) . " " . trim($m["size"])); + } + + return implode(",", $tokens); + } } diff --git a/include/functions.php b/include/functions.php index 4d54f7e35..16953a0a1 100644 --- a/include/functions.php +++ b/include/functions.php @@ -1289,19 +1289,13 @@ } if ($entry->hasAttribute('srcset')) { - $tokens = explode(",", $entry->getAttribute('srcset')); + $matches = RSSUtils::decode_srcset($entry->getAttribute('srcset')); - for ($i = 0; $i < count($tokens); $i++) { - $token = trim($tokens[$i]); - - list ($url, $width) = explode(" ", $token, 2); - - $url = rewrite_relative_url($rewrite_base_url, $url); - - $tokens[$i] = "$url $width"; + for ($i = 0; $i < count($matches); $i++) { + $matches[$i]["url"] = rewrite_relative_url($rewrite_base_url, $matches[$i]["url"]); } - $entry->setAttribute("srcset", implode(", ", $tokens)); + $entry->setAttribute("srcset", RSSUtils::encode_srcset($matches)); } if ($entry->hasAttribute('src') &&