get(0); + $emit('Page should include a main landmark', $first, 'Landmark.MissingMain'); } } diff --git a/src/Rules/Structure/SkipLinkRule.php b/src/Rules/Structure/SkipLinkRule.php index cf0e460..c480d25 100644 --- a/src/Rules/Structure/SkipLinkRule.php +++ b/src/Rules/Structure/SkipLinkRule.php @@ -18,20 +18,24 @@ public function evaluate(Tokens $tokens, int $tokenIndex, callable $emit): void return; } - // Only perform a single page-level scan (when invoked on the first - // token) to detect absence of skip links. This avoids emitting the - // same violation multiple times. + // Page-level rule: only run once (tokenIndex 0) and only for full + // pages (containing or getFullContent($tokens); - if (preg_match('/href\s*=\s*["\"]#([^"\']+)["\"][^>]*>.*?skip/i', $content)) { + if (!str_contains($content, ']*>/i', $content)) { + if (preg_match('/href\s*=\s*["\']#([^"\']+)["\'][^>]*>.*?skip/i', $content)) { + return; + } + + if (preg_match('/href\s*=\s*["\']#(main|content)["\'][^>]*>/i', $content)) { return; } diff --git a/tests/Rules/Forms/Fixtures/valid/input_hidden.html.twig b/tests/Rules/Forms/Fixtures/valid/input_hidden.html.twig new file mode 100644 index 0000000..7d97f9c --- /dev/null +++ b/tests/Rules/Forms/Fixtures/valid/input_hidden.html.twig @@ -0,0 +1,5 @@ + + +html + + diff --git a/tests/Rules/Forms/Fixtures/valid/input_with_aria_variable.html.twig b/tests/Rules/Forms/Fixtures/valid/input_with_aria_variable.html.twig new file mode 100644 index 0000000..e1aa40d --- /dev/null +++ b/tests/Rules/Forms/Fixtures/valid/input_with_aria_variable.html.twig @@ -0,0 +1,5 @@ + + + + + diff --git a/tests/Rules/Forms/InputLabelRuleTest.php b/tests/Rules/Forms/InputLabelRuleTest.php index 65840b6..cd4ebd6 100644 --- a/tests/Rules/Forms/InputLabelRuleTest.php +++ b/tests/Rules/Forms/InputLabelRuleTest.php @@ -36,5 +36,11 @@ public static function provideFixtures(): iterable __DIR__.'/Fixtures/invalid/input_no_label.html.twig', ['InputLabel.InputLabel.MissingLabel:3:1' => 'Input element must have an associated