specfold_core/markdown/frontmatter/
split.rs1pub struct Split<'a> {
4 pub raw: Option<&'a str>,
6 pub body: &'a str,
7 pub body_line: usize,
9}
10
11pub fn split(text: &str) -> Split<'_> {
12 let text = text.strip_prefix('\u{feff}').unwrap_or(text);
13 let Some(rest) = text.strip_prefix("---\n").or_else(|| text.strip_prefix("---\r\n")) else {
14 return Split { raw: None, body: text, body_line: 1 };
15 };
16 let mut offset = 0;
17 for line in rest.split_inclusive('\n') {
18 let bare = line.trim_end_matches(['\n', '\r']);
19 if bare == "---" || bare == "..." {
20 let raw = &rest[..offset];
21 return Split { raw: Some(raw), body: &rest[offset + line.len()..], body_line: raw.lines().count() + 3 };
22 }
23 offset += line.len();
24 }
25 Split { raw: None, body: text, body_line: 1 }
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31
32 #[test]
33 fn splits_block() {
34 let s = split("---\nid: x\nrel:\n a: b\n---\n# Title\n");
35 assert_eq!(s.raw, Some("id: x\nrel:\n a: b\n"));
36 assert_eq!(s.body_line, 6);
37 assert!(s.body.starts_with("# Title"));
38 }
39
40 #[test]
41 fn no_block() {
42 assert!(split("# Just a title\n").raw.is_none());
43 assert!(split("---\nunclosed\n").raw.is_none());
44 }
45}