Compare commits

...
5 Commits
Author SHA1 Message Date
Enes Yakıştır 8e6ea62ba7 chore: bump version to v3.0.4 and fix Symfony 8 compatibility 2026-07-07 13:00:44 +03:00
Enes Yakıştır c138cbca65 chore: remove BOM from composer.json 2026-07-07 12:59:20 +03:00
Enes Yakıştır 18aa4641d2 chore: bump version to v3.0.3 and update configurations 2026-07-07 12:47:34 +03:00
Enes Yakıştır c4745d6cb3 fix: resolve all WCAG 2.1 violations in demo/broken.html and bump version to 3.0.2
- Added lang attribute to html element (WCAG 3.1.1)
- Added descriptive page title (WCAG 2.4.2)
- Added alt attributes to all images (WCAG 1.1.1)
- Removed redundant alt text words (WCAG 1.1.1)
- Fixed empty link and button with discernible text (WCAG 2.4.4, 4.1.2)
- Removed positive tabindex value (WCAG 2.4.3)
- Eliminated duplicate id=main-content (WCAG 4.1.1)
- Fixed insufficient color contrast ratio (WCAG 1.4.3)
- Replaced invalid ARIA role cool-widget with region (WCAG 4.1.2)
- Added title attribute to iframe (WCAG 4.1.2)
- Replaced generic link texts with descriptive ones (WCAG 2.4.4)
- Added associated label for placeholder-only input (WCAG 3.3.2)
- Removed aria-hidden from focusable elements (WCAG 4.1.2)
- Added non-empty heading text (WCAG 2.4.6)
- Added video captions track element (WCAG 1.2.2)
- Added non-empty label text (WCAG 1.3.1)
- Added tabindex=0 to role=button div (WCAG 2.1.1)
2026-06-23 01:25:08 +03:00
Enes Yakıştır a2b984df04 fix: resolve autoloading in vendor execution and eliminate template false positives 2026-06-23 01:15:35 +03:00
9 changed files with 1223 additions and 60 deletions
+13 -6
View File
@@ -1,7 +1,14 @@
#!/usr/bin/env php #!/usr/bin/env php
<?php <?php
require __DIR__ . '/../vendor/autoload.php'; if (file_exists(__DIR__ . '/../vendor/autoload.php')) {
require __DIR__ . '/../vendor/autoload.php';
} elseif (file_exists(__DIR__ . '/../../../autoload.php')) {
require __DIR__ . '/../../../autoload.php';
} else {
echo "Autoload file not found.\n";
exit(1);
}
use Symfony\Component\Console\Application; use Symfony\Component\Console\Application;
use YakNet\AccessibilityConsole\Console\Command\ScanCommand; use YakNet\AccessibilityConsole\Console\Command\ScanCommand;
@@ -9,12 +16,12 @@ use YakNet\AccessibilityConsole\Console\Command\FixCommand;
use YakNet\AccessibilityConsole\Console\Command\InitCommand; use YakNet\AccessibilityConsole\Console\Command\InitCommand;
use YakNet\AccessibilityConsole\Console\Command\RulesCommand; use YakNet\AccessibilityConsole\Console\Command\RulesCommand;
$application = new Application('YakNet Accessibility Console', '2.9.2'); $application = new Application('YakNet Accessibility Console', '3.0.1');
// Add commands // Add commands
$application->add(new ScanCommand()); $application->addCommand(new ScanCommand());
$application->add(new FixCommand()); $application->addCommand(new FixCommand());
$application->add(new InitCommand()); $application->addCommand(new InitCommand());
$application->add(new RulesCommand()); $application->addCommand(new RulesCommand());
$application->run(); $application->run();
+5 -4
View File
@@ -12,7 +12,7 @@
"yaknet" "yaknet"
], ],
"homepage": "https://forum.yak.net.tr", "homepage": "https://forum.yak.net.tr",
"version": "3.0.0", "version": "3.0.4",
"type": "library", "type": "library",
"license": "MIT", "license": "MIT",
"authors": [ "authors": [
@@ -27,11 +27,11 @@
"ext-dom": "*", "ext-dom": "*",
"ext-libxml": "*", "ext-libxml": "*",
"ext-mbstring": "*", "ext-mbstring": "*",
"symfony/console": "^6.4|^7.0", "symfony/console": "^6.4|^7.0|^8.0",
"symfony/yaml": "^6.4|^7.0", "symfony/yaml": "^6.4|^7.0|^8.0",
"monolog/monolog": "^3.0", "monolog/monolog": "^3.0",
"vlucas/phpdotenv": "^5.6", "vlucas/phpdotenv": "^5.6",
"google-gemini-php/client": "^1.0", "google-gemini-php/client": "^1.0|^2.0",
"guzzlehttp/guzzle": "^7.8", "guzzlehttp/guzzle": "^7.8",
"masterminds/html5": "^2.8", "masterminds/html5": "^2.8",
"sabberworm/php-css-parser": "^9.4", "sabberworm/php-css-parser": "^9.4",
@@ -57,3 +57,4 @@
} }
} }
} }
+102 -47
View File
@@ -1,66 +1,121 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html lang="tr"><!-- FIXED: Added lang attribute (WCAG 3.1.1) -->
<head> <head>
<title></title> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Erişilebilir Demo Sayfa</title><!-- FIXED: Non-empty page title (WCAG 2.4.2) -->
<style>
body {
font-family: sans-serif;
margin: 0;
padding: 2rem;
background: #ffffff;
color: #1a1a1a; /* FIXED: High contrast text (WCAG 1.4.3) */
line-height: 1.6;
}
/* FIXED: Sufficient contrast (WCAG 1.4.3) - was #888 on #999, now dark on white */
.low-contrast-example {
color: #595959; /* 7:1 contrast on white */
background-color: #ffffff;
padding: 0.5rem;
}
label {
display: block;
margin-bottom: 0.25rem;
font-weight: 600;
}
input {
padding: 0.4rem;
border: 1px solid #ccc;
border-radius: 4px;
width: 100%;
max-width: 300px;
}
iframe {
border: none;
}
video {
display: block;
margin-top: 0.5rem;
}
[role="button"] {
cursor: pointer;
}
</style>
</head> </head>
<body> <body>
<h1 id="main-content">Welcome to a broken page</h1> <h1 id="main-content">Erişilebilir Demo Sayfa</h1>
<!-- FIXED: Removed duplicate id="main-content" (WCAG 4.1.1) -->
<!-- Missing alt attribute -->
<img src="logo.png">
<!-- Empty link -->
<a href="https://google.com"></a>
<!-- Empty button -->
<button type="submit"></button>
<!-- Positive tabindex -->
<a href="/keyboard" tabindex="5">Keyboard test</a>
<!-- Duplicate ID --> <!-- FIXED: Added alt attribute (WCAG 1.1.1) -->
<div id="main-content">This is a duplicate main-content ID div!</div> <img src="logo.png" alt="YakNet Şirket">
<!-- Low Contrast --> <!-- FIXED: Added descriptive link text (WCAG 2.4.4) -->
<p style="color: #888888; background-color: #999999;">This text has extremely low contrast ratio!</p> <a href="https://google.com">Google Ana Sayfasına Git</a>
<!-- Invalid ARIA role and missing controls target --> <!-- FIXED: Added discernible button text (WCAG 4.1.2) -->
<div role="cool-widget" aria-controls="non-existent-popup">WAI-ARIA elements</div> <button type="submit">Formu Gönder</button>
<!-- Missing Iframe Title --> <!-- FIXED: Removed positive tabindex (WCAG 2.4.3) — use natural DOM order -->
<iframe src="https://www.youtube.com/embed/aqz-KE-bpKQ" width="560" height="315"></iframe> <a href="/keyboard">Klavye Testi</a>
<!-- New WCAG Rule Violations for testing --> <!-- FIXED: Removed duplicate id="main-content" — unique wrapper instead -->
<div id="duplicate-content-wrapper">Bu bölümün içeriği buradadır.</div>
<!-- LinkTextGeneric: Generic text without context -->
<a href="/read-more">Click here</a>
<a href="/devam-oku">devamını oku</a>
<!-- PlaceholderAsLabel: Input relying only on placeholder -->
<input type="text" placeholder="Search website...">
<!-- ImageAltRedundant: Redundant words in alt text --> <!-- FIXED: High contrast text (WCAG 1.4.3) -->
<img src="logo2.png" alt="logo of our company"> <p class="low-contrast-example">Bu metnin kontrast oranı WCAG AA gereksinimlerini karşılamaktadır.</p>
<img src="profile.jpg" alt="profile photo of john doe">
<!-- AriaHiddenFocusable: Focusable element hidden with aria-hidden="true" --> <!-- FIXED: Valid WAI-ARIA role (WCAG 4.1.2) and removed reference to non-existent element -->
<div aria-hidden="true"> <div role="region" aria-label="WAI-ARIA Örnek Bölüm">WAI-ARIA bölüm örneği</div>
<button type="button">Hidden click</button>
<!-- FIXED: Added descriptive title to iframe (WCAG 4.1.2) -->
<iframe
src="https://www.youtube.com/embed/aqz-KE-bpKQ"
width="560"
height="315"
title="YouTube Video: Örnek Video İçeriği"
></iframe>
<!-- FIXED: Descriptive link text instead of generic "click here" / "devamını oku" (WCAG 2.4.4) -->
<a href="/read-more">Makaleyi Devamı: WCAG Erişilebilirlik Kılavuzu</a>
<a href="/devam-oku">Şiir Serisinin Devamını Oku: "Bahar Rüzgarı"</a>
<!-- FIXED: Added associated <label> element (WCAG 1.3.1 & 3.3.2) -->
<div>
<label for="search-input">Web sitesinde ara</label>
<input type="text" id="search-input" placeholder="Arama teriminizi girin...">
</div> </div>
<a href="#" aria-hidden="true">Hidden link</a>
<!-- Empty heading violation --> <!-- FIXED: Removed redundant words "logo" and "photo" from alt texts (WCAG 1.1.1) -->
<h2></h2> <img src="logo2.png" alt="Şirketimizin simgesi">
<img src="profile.jpg" alt="John Doe vesikalık">
<!-- Video missing track violation --> <!-- FIXED: Removed aria-hidden="true" from focusable elements (WCAG 4.1.2) -->
<video src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4" width="320" height="240" controls></video> <div>
<button type="button">Gizli Olmayan Tıklanabilir Düğme</button>
</div>
<a href="#">Normal Bağlantı</a>
<!-- Empty label violation --> <!-- FIXED: Added non-empty heading text (WCAG 2.4.6) -->
<label for="search-input"></label> <h2>Alt Bölüm Başlığı</h2>
<!-- AriaFocusable violation --> <!-- FIXED: Added <track> element for video captions (WCAG 1.2.2) -->
<div role="button">Clickable div button without tabindex</div> <video
src="https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4"
width="320"
height="240"
controls
>
<track kind="captions" src="captions.vtt" srclang="tr" label="Türkçe Altyazı" default>
</video>
<p>This page has multiple accessibility issues.</p> <!-- FIXED: Added non-empty label text (WCAG 1.3.1) -->
<label for="name-input">Ad Soyad</label>
<input type="text" id="name-input" name="name">
<!-- FIXED: Added tabindex="0" to make role="button" keyboard focusable (WCAG 2.1.1) -->
<div role="button" tabindex="0">Tıklanabilir Div Düğme (Erişilebilir)</div>
<p>Bu sayfa WCAG 2.1 erişilebilirlik standartlarına uygun olarak düzenlenmiştir.</p>
</body> </body>
</html> </html>
+5 -3
View File
@@ -23,9 +23,11 @@ class Analyser
$cwd = getcwd(); $cwd = getcwd();
$this->projectRoot = $cwd ? str_replace('\\', '/', realpath($cwd) ?: $cwd) : '.'; $this->projectRoot = $cwd ? str_replace('\\', '/', realpath($cwd) ?: $cwd) : '.';
$baselinePath = $this->config->getBaselinePath(); if ($baselineManager === null) {
if ($baselinePath) { $baselinePath = $this->config->getBaselinePath();
$this->baselineManager->load($this->projectRoot . '/' . $baselinePath); if ($baselinePath) {
$this->baselineManager->load($this->projectRoot . '/' . $baselinePath);
}
} }
} }
+5
View File
@@ -21,6 +21,11 @@ class ButtonName extends AbstractRule
return null; return null;
} }
$html = $element->ownerDocument ? $element->ownerDocument->saveHTML($element) : '';
if ($html !== false && preg_match('/<\?php|\{\{|\{%/i', $html)) {
return null;
}
$text = trim($element->textContent); $text = trim($element->textContent);
if ($text === '' && !$element->hasAttribute('aria-label') && !$element->hasAttribute('title')) { if ($text === '' && !$element->hasAttribute('aria-label') && !$element->hasAttribute('title')) {
return $this->createViolation($element, $this->getDescription(), 'Add text or an aria-label to the button.'); return $this->createViolation($element, $this->getDescription(), 'Add text or an aria-label to the button.');
+5
View File
@@ -21,6 +21,11 @@ class EmptyHeading extends AbstractRule
return null; return null;
} }
$html = $element->ownerDocument ? $element->ownerDocument->saveHTML($element) : '';
if ($html !== false && preg_match('/<\?php|\{\{|\{%/i', $html)) {
return null;
}
$text = trim($element->textContent); $text = trim($element->textContent);
if ($text === '' && !$element->hasAttribute('aria-label') && !$element->hasAttribute('title')) { if ($text === '' && !$element->hasAttribute('aria-label') && !$element->hasAttribute('title')) {
return $this->createViolation( return $this->createViolation(
+5
View File
@@ -21,6 +21,11 @@ class EmptyLabel extends AbstractRule
return null; return null;
} }
$html = $element->ownerDocument ? $element->ownerDocument->saveHTML($element) : '';
if ($html !== false && preg_match('/<\?php|\{\{|\{%/i', $html)) {
return null;
}
$text = trim($element->textContent); $text = trim($element->textContent);
if ($text === '') { if ($text === '') {
return $this->createViolation( return $this->createViolation(
+5
View File
@@ -21,6 +21,11 @@ class EmptyLink extends AbstractRule
return null; return null;
} }
$html = $element->ownerDocument ? $element->ownerDocument->saveHTML($element) : '';
if ($html !== false && preg_match('/<\?php|\{\{|\{%/i', $html)) {
return null;
}
$text = trim($element->textContent); $text = trim($element->textContent);
if ($text === '' && !$element->hasAttribute('aria-label') && !$element->hasAttribute('title')) { if ($text === '' && !$element->hasAttribute('aria-label') && !$element->hasAttribute('title')) {
// Check for images inside // Check for images inside
File diff suppressed because it is too large Load Diff