| 141 | |
| 142 | |
| 143 | def _line_metrics(markdown: str) -> dict[str, Any]: |
| 144 | lines = markdown.splitlines() |
| 145 | line_lengths = [len(line) for line in lines] |
| 146 | option_counts = [len(_OPTION_RE.findall(line)) for line in lines] |
| 147 | return { |
| 148 | "line_count": len(lines), |
| 149 | "nonblank_line_count": sum(1 for line in lines if line.strip()), |
| 150 | "char_count": len(markdown), |
| 151 | "max_line_length": max(line_lengths, default=0), |
| 152 | "avg_line_length": round(sum(line_lengths) / len(lines), 2) if lines else 0, |
| 153 | "giant_lines_500": sum(1 for length in line_lengths if length > 500), |
| 154 | "giant_lines_1000": sum(1 for length in line_lengths if length > 1000), |
| 155 | "option_like_tokens": sum(option_counts), |
| 156 | "max_option_like_tokens_on_line": max(option_counts, default=0), |
| 157 | "lines_with_multiple_option_like_tokens": sum( |
| 158 | 1 for count in option_counts if count >= 2 |
| 159 | ), |
| 160 | "unescaped_star_runs": len(_UNESCAPED_STAR_RUN_RE.findall(markdown)), |
| 161 | "unescaped_under_runs": len(_UNESCAPED_UNDER_RUN_RE.findall(markdown)), |
| 162 | } |
| 163 | |
| 164 | |
| 165 | def _html_metrics(html: str) -> dict[str, Any]: |