Skip to content

Commit f9dd4f7

Browse files
committed
fix(core): 🐛 avoid false front matter detection at file start
1 parent 71ad7af commit f9dd4f7

1 file changed

Lines changed: 48 additions & 11 deletions

File tree

src/audit.rs

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -279,36 +279,40 @@ fn extract_normalized_headings(readme_lower: &str) -> Vec<String> {
279279
let mut headings = Vec::new();
280280
let mut fence: Option<FenceSpec> = None;
281281
let mut front_matter_possible = true;
282-
let mut in_front_matter = false;
282+
let mut front_matter_end_index: Option<usize> = None;
283283
let lines: Vec<&str> = readme_lower.lines().collect();
284284
let mut index = 0usize;
285285

286286
while index < lines.len() {
287287
let trimmed = lines[index].trim_start();
288288
let trimmed_both = lines[index].trim();
289289

290+
if let Some(end_index) = front_matter_end_index
291+
&& index <= end_index
292+
{
293+
if index == end_index {
294+
front_matter_end_index = None;
295+
}
296+
index += 1;
297+
continue;
298+
}
299+
290300
if front_matter_possible && trimmed_both.is_empty() {
291301
index += 1;
292302
continue;
293303
}
294304

295305
if front_matter_possible {
296306
front_matter_possible = false;
297-
if trimmed_both == "---" || trimmed_both == "+++" {
298-
in_front_matter = true;
307+
if (trimmed_both == "---" || trimmed_both == "+++")
308+
&& let Some(end_index) = find_front_matter_end(&lines, index, trimmed_both)
309+
{
310+
front_matter_end_index = Some(end_index);
299311
index += 1;
300312
continue;
301313
}
302314
}
303315

304-
if in_front_matter {
305-
if trimmed_both == "---" || trimmed_both == "+++" || trimmed_both == "..." {
306-
in_front_matter = false;
307-
}
308-
index += 1;
309-
continue;
310-
}
311-
312316
if let Some(current_fence) = fence {
313317
if is_closing_fence(trimmed, current_fence) {
314318
fence = None;
@@ -355,6 +359,25 @@ fn extract_normalized_headings(readme_lower: &str) -> Vec<String> {
355359
headings
356360
}
357361

362+
fn find_front_matter_end(lines: &[&str], opening_index: usize, delimiter: &str) -> Option<usize> {
363+
let mut has_metadata_like_line = false;
364+
365+
for (index, line) in lines.iter().enumerate().skip(opening_index + 1) {
366+
let trimmed = line.trim();
367+
368+
let is_closing_delimiter = trimmed == delimiter || (delimiter == "---" && trimmed == "...");
369+
if is_closing_delimiter {
370+
return has_metadata_like_line.then_some(index);
371+
}
372+
373+
if !trimmed.is_empty() && trimmed.contains(':') {
374+
has_metadata_like_line = true;
375+
}
376+
}
377+
378+
None
379+
}
380+
358381
fn parse_opening_fence(trimmed_line: &str) -> Option<FenceSpec> {
359382
let mut chars = trimmed_line.chars();
360383
let marker = chars.next()?;
@@ -626,4 +649,18 @@ features: false
626649
let audit = audit_repo(&example_repo(), Some(readme), 70, false);
627650
assert!(audit.missing_required.contains(&"Features"));
628651
}
652+
653+
#[test]
654+
fn does_not_treat_unclosed_horizontal_rule_as_front_matter() {
655+
let readme = "
656+
---
657+
## Features
658+
## Quick Start
659+
## Architecture
660+
## License
661+
";
662+
663+
let audit = audit_repo(&example_repo(), Some(readme), 70, false);
664+
assert!(audit.missing_required.is_empty());
665+
}
629666
}

0 commit comments

Comments
 (0)