diff --git a/includes/class-support.php b/includes/class-support.php
index bfc9829..767999f 100644
--- a/includes/class-support.php
+++ b/includes/class-support.php
@@ -17,8 +17,8 @@ public function init(): void
$this->uploadsInfo = \wp_upload_dir();
$this->fileCache = \get_transient('avif_local_support_file_cache') ?: [];
add_filter('wp_get_attachment_image', [$this, 'wrapAttachment'], 10, 5);
- add_filter('the_content', [$this, 'wrapContentImages']);
- add_filter('post_thumbnail_html', [$this, 'wrapContentImages']);
+ add_filter('wp_content_img_tag', [$this, 'wrapContentImgTag'], 10, 3);
+ add_filter('post_thumbnail_html', [$this, 'wrapSingleImageHtml'], 10, 1);
add_action('shutdown', [$this, 'saveCache']);
}
@@ -50,65 +50,112 @@ public function wrapAttachment(string $html, int $attachmentId, $size, bool $ico
return $this->pictureMarkup($html, $avifSrc, $avifSrcset, $sizes);
}
- public function wrapContentImages(string $content): string
+ public function wrapContentImgTag(string $html, string $context, int $attachmentId): string
{
if (\is_admin() || \wp_doing_ajax() || (\defined('REST_REQUEST') && REST_REQUEST)) {
- return $content;
+ return $html;
}
- if (!str_contains($content, '
uploadsInfo['baseurl'] ?? '';
- if (!$uploadsUrl) {
- return $content;
+ if (!preg_match('/src=["\']([^"\']+)["\']/', $html, $srcMatch)) {
+ return $html;
+ }
+ $src = $srcMatch[1];
+ if (!$this->isUploadsImage($src)) {
+ return $html;
}
- $pattern = sprintf(
- '/
]*?)src=["\'](%s[^"\']*\.(?:jpe?g|JPE?G))["\']([^>]*?)>/i',
- preg_quote($uploadsUrl, '/')
- );
-
- $result = preg_replace_callback($pattern, function (array $matches): string {
- $fullTag = $matches[0];
- $src = $matches[2];
-
- $avifSrc = $this->avifUrlFor($src);
- if (!$avifSrc) {
- return $fullTag;
- }
+ $avifSrc = $this->avifUrlFor($src);
+ if (!$avifSrc) {
+ return $html;
+ }
- $avifSrcset = $avifSrc;
- if (preg_match('/srcset=["\']([^"\']*)["\']/', $fullTag, $srcsetMatches)) {
- $converted = $this->convertSrcsetToAvif($srcsetMatches[1]);
- if ($converted) {
- $avifSrcset = $converted;
- }
+ $avifSrcset = $avifSrc;
+ if (preg_match('/srcset=["\']([^"\']*)["\']/', $html, $srcsetMatches)) {
+ $converted = $this->convertSrcsetToAvif($srcsetMatches[1]);
+ if ($converted) {
+ $avifSrcset = $converted;
}
+ }
- $sizes = '';
- if (preg_match('/sizes=["\']([^"\']*)["\']/', $fullTag, $sizesMatches)) {
- $sizes = $sizesMatches[1];
- }
+ $sizes = '';
+ if (preg_match('/sizes=["\']([^"\']*)["\']/', $html, $sizesMatches)) {
+ $sizes = $sizesMatches[1];
+ }
- return $this->pictureMarkup($fullTag, $avifSrc, $avifSrcset, $sizes);
- }, $content);
+ return $this->pictureMarkup($html, $avifSrc, $avifSrcset, $sizes);
+ }
- return $result !== null ? $result : $content;
+ public function wrapSingleImageHtml(string $html): string
+ {
+ if ($html === '' || str_contains($html, 'isUploadsImage($src)) {
+ return $html;
+ }
+ $avifSrc = $this->avifUrlFor($src);
+ if (!$avifSrc) {
+ return $html;
+ }
+ $avifSrcset = $avifSrc;
+ if (preg_match('/srcset=["\']([^"\']*)["\']/', $html, $srcsetMatches)) {
+ $converted = $this->convertSrcsetToAvif($srcsetMatches[1]);
+ if ($converted) {
+ $avifSrcset = $converted;
+ }
+ }
+ $sizes = '';
+ if (preg_match('/sizes=["\']([^"\']*)["\']/', $html, $sizesMatches)) {
+ $sizes = $sizesMatches[1];
+ }
+ return $this->pictureMarkup($html, $avifSrc, $avifSrcset, $sizes);
}
private function avifUrlFor(string $jpegUrl): ?string
{
- if (!$this->isUploadsImage($jpegUrl) || !preg_match('/\.(jpe?g|JPE?G)$/', $jpegUrl)) {
+ if (!$this->isUploadsImage($jpegUrl)) {
return null;
}
- $avifUrl = preg_replace('/\.(jpe?g|JPE?G)$/i', '.avif', $jpegUrl);
- $relative = str_replace($this->uploadsInfo['baseurl'] ?? '', '', (string) $avifUrl);
+
+ $queryString = '';
+ $jpegUrlNoQuery = $jpegUrl;
+ $hashPos = strpos($jpegUrl, '#');
+ $qPos = strpos($jpegUrl, '?');
+ $cutPos = false;
+ if ($qPos !== false && $hashPos !== false) {
+ $cutPos = min($qPos, $hashPos);
+ } elseif ($qPos !== false) {
+ $cutPos = $qPos;
+ } elseif ($hashPos !== false) {
+ $cutPos = $hashPos;
+ }
+ if ($cutPos !== false) {
+ $queryString = substr($jpegUrl, (int) $cutPos);
+ $jpegUrlNoQuery = substr($jpegUrl, 0, (int) $cutPos);
+ }
+
+ if (!preg_match('/\.(jpe?g|JPE?G)$/', $jpegUrlNoQuery)) {
+ return null;
+ }
+
+ $avifNoQuery = preg_replace('/\.(jpe?g|JPE?G)$/i', '.avif', $jpegUrlNoQuery);
+ $relative = str_replace($this->uploadsInfo['baseurl'] ?? '', '', (string) $avifNoQuery);
$avifLocal = ($this->uploadsInfo['basedir'] ?? '') . $relative;
- return $this->avifExists($avifLocal) ? $avifUrl : null;
+ if (!$this->avifExists($avifLocal)) {
+ return null;
+ }
+
+ return $avifNoQuery . $queryString;
}
private function isUploadsImage(string $src): bool