feat(v3.2.7): expand WCAG ruleset to 127 rules, add HTML syntax linter, single-pass rule engine, template preprocessor, and accessibility analytics

This commit is contained in:
Enes Yakıştır
2026-08-16 22:00:30 +03:00
parent 9a6784ad19
commit 2de1f34878
93 changed files with 4879 additions and 305 deletions
+22 -9
View File
@@ -6,15 +6,28 @@ class BladeParser implements ParserInterface
{
public function parse(string $content): string
{
// Replace {!! ... !!} with static text
$content = preg_replace('/\{\!\!(.*?)\!\!\}/s', 'StaticRawBladeContent', $content) ?? $content;
// Replace {{ ... }} with static text
$content = preg_replace('/\{\{\s*(.*?)\s*\}\}/s', 'StaticBladeContent', $content) ?? $content;
// Strip Blade directives like @if, @else, @endif, @foreach, @endforeach, etc.
$content = preg_replace('/@[a-zA-Z0-9_]+\s*(\(.*?\))?/i', '', $content) ?? $content;
// 1. Strip Blade comments {{-- ... --}} while preserving line count
$content = preg_replace_callback('/\{\{--(.*?)--\}\}/s', function ($m) {
return str_repeat("\n", substr_count($m[0], "\n"));
}, $content) ?? $content;
// 2. Replace raw echo {!! ... !!} while preserving line count
$content = preg_replace_callback('/\{\!\!(.*?)\!\!\}/s', function ($m) {
$newlines = str_repeat("\n", substr_count($m[0], "\n"));
return 'StaticRawBladeContent' . $newlines;
}, $content) ?? $content;
// 3. Replace safe echo {{ ... }} while preserving line count
$content = preg_replace_callback('/\{\{\s*(.*?)\s*\}\}/s', function ($m) {
$newlines = str_repeat("\n", substr_count($m[0], "\n"));
return 'StaticBladeContent' . $newlines;
}, $content) ?? $content;
// 4. Strip Blade directives like @if, @else, @endif, @foreach, @component, etc.
$content = preg_replace_callback('/@[a-zA-Z0-9_]+\s*(\([^\)]*\))?/s', function ($m) {
return str_repeat("\n", substr_count($m[0], "\n"));
}, $content) ?? $content;
return $content;
}
}
+74
View File
@@ -0,0 +1,74 @@
<?php
namespace YakNet\AccessibilityConsole\Parser;
class TemplatePreprocessor
{
private BladeParser $bladeParser;
private TwigParser $twigParser;
private HtmlParser $htmlParser;
public function __construct(
?BladeParser $bladeParser = null,
?TwigParser $twigParser = null,
?HtmlParser $htmlParser = null
) {
$this->bladeParser = $bladeParser ?? new BladeParser();
$this->twigParser = $twigParser ?? new TwigParser();
$this->htmlParser = $htmlParser ?? new HtmlParser();
}
/**
* Preprocess file content according to its file extension or template dialect.
*
* @param string $content
* @param string|null $filePath
* @return string
*/
public function preprocess(string $content, ?string $filePath = null): string
{
if ($filePath !== null) {
$lower = strtolower($filePath);
if (str_ends_with($lower, '.blade.php')) {
return $this->bladeParser->parse($content);
}
if (str_ends_with($lower, '.twig')) {
return $this->twigParser->parse($content);
}
if (str_ends_with($lower, '.php')) {
return $this->preprocessPhp($content);
}
}
// Detect Blade or Twig by content heuristic if no path is provided
if (str_contains($content, '{{') || str_contains($content, '@if') || str_contains($content, '@foreach')) {
return $this->bladeParser->parse($content);
}
if (str_contains($content, '{%') || str_contains($content, '{#')) {
return $this->twigParser->parse($content);
}
if (str_contains($content, '<' . '?php') || str_contains($content, '<' . '?=')) {
return $this->preprocessPhp($content);
}
return $this->htmlParser->parse($content);
}
private function preprocessPhp(string $content): string
{
// Replace short echo tags with placeholder text preserving newlines
$content = preg_replace_callback('/<\?=(.*?)\?>/s', function ($m) {
$newlines = str_repeat("\n", substr_count($m[0], "\n"));
return 'StaticPhpEcho' . $newlines;
}, $content) ?? $content;
// Replace PHP execution blocks with placeholder preserving newlines
$content = preg_replace_callback('/<\?php(.*?)\?>/s', function ($m) {
return str_repeat("\n", substr_count($m[0], "\n"));
}, $content) ?? $content;
return $content;
}
}
+16 -9
View File
@@ -6,15 +6,22 @@ class TwigParser implements ParserInterface
{
public function parse(string $content): string
{
// Strip Twig comments {# ... #}
$content = preg_replace('/\{\#.*?\#\}/s', '', $content) ?? $content;
// Replace Twig output {{ ... }} with static text
$content = preg_replace('/\{\{\s*(.*?)\s*\}\}/s', 'StaticTwigOutput', $content) ?? $content;
// Strip Twig statements {% ... %}
$content = preg_replace('/\{\%.*?\%\}/s', '', $content) ?? $content;
// 1. Strip Twig comments {# ... #} while preserving line count
$content = preg_replace_callback('/\{\#.*?\#\}/s', function ($m) {
return str_repeat("\n", substr_count($m[0], "\n"));
}, $content) ?? $content;
// 2. Replace Twig output {{ ... }} while preserving line count
$content = preg_replace_callback('/\{\{\s*(.*?)\s*\}\}/s', function ($m) {
$newlines = str_repeat("\n", substr_count($m[0], "\n"));
return 'StaticTwigOutput' . $newlines;
}, $content) ?? $content;
// 3. Strip Twig statements {% ... %} while preserving line count
$content = preg_replace_callback('/\{\%.*?\%\}/s', function ($m) {
return str_repeat("\n", substr_count($m[0], "\n"));
}, $content) ?? $content;
return $content;
}
}