From ee7e05f9368ba1dbb5217c502e86667d12b51c98 Mon Sep 17 00:00:00 2001 From: Andrew Welch Date: Sat, 19 Oct 2024 19:33:56 -0400 Subject: [PATCH] feat: Allow for empty `alt` tags for screen readers as per WCAG ([411](https://github.com/nystudio107/craft-imageoptimize/issues/411)) --- src/models/BaseTag.php | 19 +++++++++++++++++++ src/models/ImgTag.php | 9 ++------- src/models/LinkPreloadTag.php | 2 +- src/models/PictureTag.php | 9 ++------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/models/BaseTag.php b/src/models/BaseTag.php index 1874439e..5ee1eec4 100644 --- a/src/models/BaseTag.php +++ b/src/models/BaseTag.php @@ -23,6 +23,11 @@ abstract class BaseTag extends Model implements TagInterface { use TagTrait; + /** + * Attributes that are allowed to be an empty string + */ + protected const ALLOWED_EMPTY_ATTRS = ['alt']; + /** * @return string */ @@ -40,4 +45,18 @@ public function render(): Markup { return Template::raw(''); } + + /** + * Filter out attributes with empty values in them, so they don't get rendered + * + * @param array $attrs + * @return array + */ + public function filterEmptyAttributes(array $attrs): array + { + return array_filter($attrs, static function($value, $key) { + // Keep certain attributes even if they are empty + return in_array($key, self::ALLOWED_EMPTY_ATTRS, true) || !empty($value); + }, ARRAY_FILTER_USE_BOTH); + } } diff --git a/src/models/ImgTag.php b/src/models/ImgTag.php index d5ecdc1c..67a5c9c6 100644 --- a/src/models/ImgTag.php +++ b/src/models/ImgTag.php @@ -106,13 +106,8 @@ public function render(): Markup if ($this->loadingStrategy !== 'eager') { $attrs = $this->swapLazyLoadAttrs($this->loadingStrategy, $this->placeholder, $attrs); } - - // Remove any empty attributes except the alt attribute - $attrs = array_filter($attrs, function($value, $key) { - // Keep the 'alt' attribute even if it's empty - return $key === 'alt' || !empty($value); - }, ARRAY_FILTER_USE_BOTH); - + // Remove any empty attributes + $attrs = $this->filterEmptyAttributes($attrs); // Render the tag $tag = Html::tag('img', '', $attrs); diff --git a/src/models/LinkPreloadTag.php b/src/models/LinkPreloadTag.php index 753574ee..042f6e54 100644 --- a/src/models/LinkPreloadTag.php +++ b/src/models/LinkPreloadTag.php @@ -70,7 +70,7 @@ public function render(): Markup { $attrs = $this->linkAttrs; // Remove any empty attributes - $attrs = array_filter($attrs); + $attrs = $this->filterEmptyAttributes($attrs); // Render the tag $tag = Html::tag('link', '', $attrs); diff --git a/src/models/PictureTag.php b/src/models/PictureTag.php index 846be1a8..9792959c 100644 --- a/src/models/PictureTag.php +++ b/src/models/PictureTag.php @@ -174,13 +174,8 @@ public function render(): Markup if ($this->loadingStrategy !== 'eager') { $attrs = $this->swapLazyLoadAttrs($this->loadingStrategy, $this->placeholder, $attrs); } - - // Remove any empty attributes except the alt attribute - $attrs = array_filter($attrs, function($value, $key) { - // Keep the 'alt' attribute even if it's empty - return $key === 'alt' || !empty($value); - }, ARRAY_FILTER_USE_BOTH); - + // Remove any empty attributes + $attrs = $this->filterEmptyAttributes($attrs); // Render the tag $content .= Html::tag('img', '', $attrs); // Handle the tag