tagName) !== 'img') { return null; } if (!$element->hasAttribute('alt')) { return null; } $alt = trim($element->getAttribute('alt')); if ($alt === '') { return null; // Empty alt is allowed for decorative images (WCAG 1.1.1) } $cleanAlt = strtolower($alt); // Generic placeholder checks $placeholders = [ 'image', 'photo', 'picture', 'logo', 'icon', 'placeholder', 'untitled', 'temp', 'blank', 'pic', 'dot', 'resim', 'foto', 'fotoğraf', 'görsel', 'grafik', 'ikon', 'logo', 'arkaplan', 'kapak', 'simge', 'ürün', 'dosya', 'adsız', 'varsayılan', 'default', 'hero', 'no-image', 'noimage', 'null' ]; if (in_array($cleanAlt, $placeholders, true)) { return $this->createViolation( $element, $this->getDescription(), 'Provide a specific description of what the image shows, rather than using a generic word.' ); } // Filename checks if (preg_match('/^[^\s]+\.(png|jpg|jpeg|gif|svg|webp|bmp)$/i', $cleanAlt) || preg_match('/\.(png|jpg|jpeg|gif|svg|webp|bmp)$/i', $cleanAlt)) { return $this->createViolation( $element, 'Image alt text should not be a filename.', 'Provide a descriptive alternative text instead of the image filename.' ); } return null; } }