diff --git a/bin/a11y b/bin/a11y
index 8be8b56..84d2e04 100644
--- a/bin/a11y
+++ b/bin/a11y
@@ -18,7 +18,7 @@ use YakNet\AccessibilityConsole\Console\Command\InitCommand;
use YakNet\AccessibilityConsole\Console\Command\RulesCommand;
$container = ContainerFactory::create();
-$application = new Application('YakNet Accessibility Console', '3.1.2');
+$application = new Application('YakNet Accessibility Console', '3.2.0');
// Add commands resolved via DI Container
$application->addCommand($container->get(ScanCommand::class));
diff --git a/composer.json b/composer.json
index f64bf70..1114cb6 100644
--- a/composer.json
+++ b/composer.json
@@ -12,7 +12,7 @@
"yaknet"
],
"homepage": "https://forum.yak.net.tr",
- "version": "3.1.4",
+ "version": "3.2.0",
"type": "library",
"license": "MIT",
"authors": [
@@ -39,7 +39,11 @@
"sebastian/diff": "^5.1 || ^6.0 || ^7.0 || ^8.0 || ^9.0",
"php-di/php-di": "^7.1",
"symfony/css-selector": "^8.1",
- "symfony/dom-crawler": "^8.1"
+ "symfony/dom-crawler": "^8.1",
+ "spatie/color": "^1.5",
+ "intervention/image": "^3.0",
+ "dompdf/dompdf": "^3.0",
+ "phpoffice/phpspreadsheet": "^2.0 || ^3.0"
},
"require-dev": {
"phpunit/phpunit": "^10.5",
diff --git a/dashboard/public/index.html b/dashboard/public/index.html
new file mode 100644
index 0000000..5cad2c4
--- /dev/null
+++ b/dashboard/public/index.html
@@ -0,0 +1,103 @@
+
+
+
+
+
+ YakNet Accessibility Console - Live Web Dashboard
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Erişilebilirlik Skoru
+
+
WCAG 2.1 AA Standartı
+
+
+
+
+
+
Toplam İhlal
+
+
Sıfır Kritik Hata
+
+
+
+
Aktif Kurallar
+
+
Otomatik WCAG Motoru
+
+
+
+
Yapay Zeka Onarımı
+
+
Gemini AI AutoHeal Motoru
+
+
+
+
+
+ 📋 Tespit Edilen WCAG İhlalleri
+
+ Henüz tarama başlatılmadı veya sitede ihlal bulunmadı.
+
+
+
+
+
+
+
diff --git a/dashboard/server.php b/dashboard/server.php
new file mode 100644
index 0000000..36ac026
--- /dev/null
+++ b/dashboard/server.php
@@ -0,0 +1,23 @@
+web(append: [
+ AccessibilityMiddleware::class,
+]);
+```
+
+### Automated PHPUnit / Pest Testing
+```php
+use YakNet\AccessibilityConsole\Stubs\Laravel\AssertsAccessibility;
+
+class ExampleTest extends TestCase
+{
+ use AssertsAccessibility;
+
+ public function test_homepage_is_accessible(): void
+ {
+ $this->assertPageIsAccessible('https://localhost', minScore: 90);
+ }
+}
+```
+
+## 2. WordPress Integration
+
+Drop `stubs/wordpress/yaknet-a11y-wp-plugin.php` into your `wp-content/plugins/` folder to get live admin bar WCAG badges and automatic scanning.
diff --git a/docs/RULES.md b/docs/RULES.md
new file mode 100644
index 0000000..8598f19
--- /dev/null
+++ b/docs/RULES.md
@@ -0,0 +1,25 @@
+# ♿ YakNet Accessibility Console — WCAG 2.1 Rules Reference
+
+YakNet Accessibility Console features **110 automated WCAG 2.1 rules** across Levels A, AA, and AAA.
+
+## Rule Categories
+
+### 1. ARIA & Roles (`src/Rules/Aria/`)
+- `WCAG_1_3_1_ARIA_REQUIRED_CHILDREN`: Ensures ARIA parent roles contain required child roles (e.g. `role="radiogroup"`).
+- `WCAG_4_1_2_ARIA_TOGGLE_PRESSED`: Validates `aria-pressed` states on custom toggle buttons.
+
+### 2. Form & Controls (`src/Rules/Form/`)
+- `WCAG_1_3_5_AUTOCOMPLETE`: Validates HTML5 autocomplete attributes on personal input fields.
+- `WCAG_4_1_2_PASSWORD_VISIBILITY_TOGGLE`: Ensures password visibility buttons have accessible names.
+
+### 3. Color & Vision (`src/Rules/Color/`)
+- `WCAG_1_4_1_COLOR_BLINDNESS_CONTRAST`: Simulates Deuteranopia and Protanopia vision deficiencies to verify contrast.
+- `WCAG_1_4_3_CONTRAST`: Verifies minimum 4.5:1 text-to-background contrast ratio.
+
+### 4. Landmarks & Structure (`src/Rules/Landmark/`)
+- `WCAG_1_3_1_LandmarkMain`: Enforces a single `` landmark element per document.
+- `WCAG_1_3_1_CONTENTINFO_PARENT`: Ensures `footer` contentinfo landmark is placed at top level.
+
+### 5. Media & Images (`src/Rules/Image/`)
+- `WCAG_1_1_1_SVG`: Ensures SVG graphics contain alternative text or `aria-hidden="true"`.
+- `WCAG_1_4_4_IMAGE_DIMENSIONS_SCALE`: Audits layout shift and touch target sizes (minimum 24x24px).
diff --git a/src/Audit/SiteCrawler.php b/src/Audit/SiteCrawler.php
new file mode 100644
index 0000000..4fafdeb
--- /dev/null
+++ b/src/Audit/SiteCrawler.php
@@ -0,0 +1,76 @@
+scanner = $scanner ?? new Scanner();
+ }
+
+ /**
+ * Crawl and scan multiple pages of a website up to a maximum page limit.
+ *
+ * @param string $baseUrl Base URL to start crawling
+ * @param int $maxPages Maximum number of pages to audit
+ * @return array Aggregated site-wide audit results
+ */
+ public function crawlAndAudit(string $baseUrl, int $maxPages = 5): array
+ {
+ /** @var array $visited */
+ $visited = [];
+ $queue = [$baseUrl];
+ /** @var array $results */
+ $results = [];
+
+ while (!empty($queue) && count($visited) < $maxPages) {
+ $url = array_shift($queue);
+ if (empty($url) || isset($visited[$url])) {
+ continue;
+ }
+
+ $visited[$url] = true;
+ try {
+ $html = @file_get_contents($url);
+ $violations = $html !== false ? $this->scanner->scan($html) : [];
+ $score = max(0, 100 - count($violations) * 3);
+
+ $results[$url] = [
+ 'score' => $score,
+ 'violations_count' => count($violations),
+ 'violations' => $violations,
+ ];
+ } catch (\Throwable $e) {
+ $results[$url] = ['error' => $e->getMessage(), 'score' => 0];
+ }
+ }
+
+ $scores = [];
+ $totalViolations = 0;
+ foreach ($results as $res) {
+ if (is_array($res)) {
+ if (isset($res['score']) && is_numeric($res['score'])) {
+ $scores[] = intval($res['score']);
+ }
+ if (isset($res['violations_count']) && is_numeric($res['violations_count'])) {
+ $totalViolations += intval($res['violations_count']);
+ }
+ }
+ }
+
+ $avgScore = count($scores) > 0 ? (int)round(array_sum($scores) / count($scores)) : 0;
+
+ return [
+ 'base_url' => $baseUrl,
+ 'pages_audited' => count($visited),
+ 'average_score' => $avgScore,
+ 'total_violations' => $totalViolations,
+ 'page_results' => $results,
+ ];
+ }
+}
diff --git a/src/AutoFix/HtmlRepairEngine.php b/src/AutoFix/HtmlRepairEngine.php
new file mode 100644
index 0000000..14e0710
--- /dev/null
+++ b/src/AutoFix/HtmlRepairEngine.php
@@ -0,0 +1,49 @@
+}
+ */
+ public static function autoRepair(string $html): array
+ {
+ $fixes = [];
+ $repaired = $html;
+
+ // 1. Ensure attribute
+ if (preg_match('/]*\blang=)[^>]*>/i', $repaired)) {
+ $repaired = preg_replace('/]*)>/i', '', $repaired) ?? $repaired;
+ $fixes[] = 'Added missing lang="tr" attribute to tag.';
+ }
+
+ // 2. Add aria-hidden="true" to decorative