@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Stylist\Services;
|
||||
|
||||
use Illuminate\Filesystem\Filesystem;
|
||||
use Modules\Stylist\Theme\Theme;
|
||||
|
||||
final class ThemeAccessibilityValidator
|
||||
{
|
||||
public function __construct(private readonly Filesystem $files) {}
|
||||
|
||||
/** @return array<int, array{severity:string,message:string,file:string}> */
|
||||
public function validate(Theme $theme): array
|
||||
{
|
||||
$issues = [];
|
||||
|
||||
foreach ($this->files->allFiles($theme->path().'/views') as $file) {
|
||||
$content = $file->getContents();
|
||||
$relative = $file->getRelativePathname();
|
||||
|
||||
$missingAlt = 0;
|
||||
if (preg_match_all('/<img\\b(?:(?:"[^"]*")|(?:\'[^\']*\')|[^\'">])*>/is', $content, $images)) {
|
||||
foreach ($images[0] as $image) {
|
||||
if (! preg_match('/\\balt\\s*=\\s*(?:"[^"]*"|\'[^\']*\')/is', $image)) {
|
||||
$missingAlt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($missingAlt > 0) {
|
||||
$issues[] = [
|
||||
'severity' => 'error',
|
||||
'message' => $missingAlt.' image(s) missing alt text.',
|
||||
'file' => $relative,
|
||||
];
|
||||
}
|
||||
|
||||
if (preg_match('/<html\\b(?![^>]*\\blang=)/i', $content)) {
|
||||
$issues[] = [
|
||||
'severity' => 'warning',
|
||||
'message' => 'HTML element is missing a lang attribute.',
|
||||
'file' => $relative,
|
||||
];
|
||||
}
|
||||
|
||||
$unnamedButtons = 0;
|
||||
if (preg_match_all('/<button\\b((?:(?:"[^"]*")|(?:\'[^\']*\')|[^\'">])*)>(.*?)<\\/button>/is', $content, $buttons, PREG_SET_ORDER)) {
|
||||
foreach ($buttons as $button) {
|
||||
$attributes = $button[1];
|
||||
$body = $button[2];
|
||||
|
||||
$hasAccessibleAttribute = preg_match('/\\b(?:aria-label|aria-labelledby|title)\\s*=\\s*(?:"[^"]+"|\'[^\']+\')/is', $attributes) === 1;
|
||||
$visibleText = trim(html_entity_decode(strip_tags($body), ENT_QUOTES | ENT_HTML5));
|
||||
|
||||
if (! $hasAccessibleAttribute && $visibleText === '') {
|
||||
$unnamedButtons++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($unnamedButtons > 0) {
|
||||
$issues[] = [
|
||||
'severity' => 'warning',
|
||||
'message' => $unnamedButtons.' button(s) may lack an accessible name.',
|
||||
'file' => $relative,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $issues;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user