$localeContent) { if (is_array($localeContent)) { $localeIssues = $this->analyzeBlocks($localeContent); if (!empty($localeIssues)) { $allIssues[$locale] = $localeIssues; } } } return $allIssues; } return $this->analyzeBlocks($content); } /** * Internal helper to analyze a flat list of blocks. * * @param array $content * @return array */ protected function analyzeBlocks(array $content): array { $issues = []; $headings = []; foreach ($content as $index => $block) { $type = $block['type'] ?? ''; $data = $block['data'] ?? []; switch ($type) { case 'heading': $level = (int) ($data['level'] ?? 0); if ($level > 0) { $headings[] = [ 'level' => $level, 'index' => $index ]; } break; case 'image': $alt = $data['alt'] ?? ''; if (empty($alt)) { $issues[] = [ 'severity' => 'error', 'message' => 'Image block is missing alternative text (alt tag).', 'block_index' => $index, ]; } break; case 'media': $alt = $data['alt'] ?? ''; if (empty($alt)) { $issues[] = [ 'severity' => 'warning', 'message' => 'Media block may be missing alternative text.', 'block_index' => $index, ]; } break; } } if (!empty($headings)) { $prevLevel = 0; foreach ($headings as $h) { $level = $h['level']; if ($prevLevel > 0 && $level > $prevLevel + 1) { $issues[] = [ 'severity' => 'warning', 'message' => "Skipped heading level from H$prevLevel to H$level. Headings should be sequential.", 'block_index' => $h['index'], ]; } $prevLevel = $level; } } return $issues; } }