Browse Source

better support for image srcset attributes as discussed in https://community.tt-rss.org/t/problem-with-img-srcset/3519

Andrew Dolgov 1 month ago
parent
commit
6eb94f1e13
3 changed files with 43 additions and 25 deletions
  1. 5 8
      classes/diskcache.php
  2. 34 7
      classes/rssutils.php
  3. 4 10
      include/functions.php

+ 5 - 8
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));
 				}
 			}
 

+ 34 - 7
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<url>(?!,)\S+(?<!,))\s*(?P<size>\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);
+	}
 }

+ 4 - 10
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') &&