use crate::convert::openspec::read::{fence_mask, heading_level};
use crate::convert::openspec::statement::{first_modal, metadata_entry};
pub(super) struct Read {
pub text: String,
pub scenario: bool,
}
impl Read {
pub fn modal(&self) -> bool {
first_modal(&self.text).is_some()
}
pub fn length(&self) -> usize {
self.text.chars().count()
}
}
pub(super) fn read(lines: &[String]) -> Read {
let fenced = fence_mask(lines);
let level = |index: usize| heading_level(&lines[index]).filter(|_| !fenced[index]);
let (mut text, mut metadata) = (Vec::new(), Vec::new());
for (index, line) in lines.iter().enumerate() {
if fenced[index] {
continue;
}
if level(index).is_some() {
break;
}
let trimmed = line.trim();
if metadata_entry(trimmed).is_some() {
metadata.push(trimmed);
} else if !trimmed.is_empty() {
text.push(trimmed);
}
}
let scenario = (0..lines.len())
.filter(|&index| level(index) == Some(4))
.any(|start| {
(start + 1..lines.len())
.take_while(|&index| level(index).is_none_or(|level| level > 4))
.any(|index| !lines[index].trim().is_empty())
});
Read {
text: if text.is_empty() { metadata } else { text }.join("\n"),
scenario,
}
}