1mod accordion;
8mod callout;
9mod card;
10mod code_group;
11mod content;
12mod fields;
13mod frontmatter;
14mod heading;
15mod openapi_parser;
16mod openapi_tag;
17mod openapi_types;
18mod steps;
19mod tabs;
20mod types;
21mod update;
22mod utils;
23
24pub use content::{get_raw_markdown, parse_mdx};
25pub use frontmatter::extract_frontmatter;
26pub use heading::strip_leading_h1;
27pub use openapi_parser::{OpenApiError, parse_openapi};
28pub use openapi_types::*;
29pub use types::*;
30
31pub fn parse_document(content: &str) -> ParsedDoc {
37 let (frontmatter, remaining) = extract_frontmatter(content);
38 let body = strip_leading_h1(remaining);
41 let nodes = content::parse_body(body);
44 let raw_markdown = get_raw_markdown(&nodes);
45
46 ParsedDoc {
47 frontmatter,
48 content: nodes,
49 raw_markdown,
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn parse_document_strips_duplicate_atx_h1() {
59 let content = "---\ntitle: Hello\n---\n\n# Hello\n\nbody text\n";
60 let doc = parse_document(content);
61 assert_eq!(doc.frontmatter.title, "Hello");
62 assert!(
63 !doc.raw_markdown.contains("# Hello"),
64 "expected leading H1 to be stripped, got: {:?}",
65 doc.raw_markdown
66 );
67 assert!(doc.raw_markdown.contains("body text"));
68 }
69
70 #[test]
71 fn parse_document_leaves_body_without_leading_h1_untouched() {
72 let content = "---\ntitle: Hello\n---\n\nintro paragraph\n\n## Subheading\n";
73 let doc = parse_document(content);
74 assert!(doc.raw_markdown.contains("intro paragraph"));
75 assert!(doc.raw_markdown.contains("## Subheading"));
76 }
77
78 #[test]
79 fn parse_document_preserves_h1_appearing_mid_document() {
80 let content = "---\ntitle: Hello\n---\n\nintro\n\n# Later heading\n\nmore body\n";
81 let doc = parse_document(content);
82 assert!(doc.raw_markdown.contains("intro"));
83 assert!(
84 doc.raw_markdown.contains("# Later heading"),
85 "mid-document H1 should survive, got: {:?}",
86 doc.raw_markdown
87 );
88 }
89
90 #[test]
91 fn parse_document_keeps_body_starting_with_thematic_break() {
92 let content = "---\ntitle: T\n---\n\n---\n\nfirst para\n\n---\n\nsecond para\n";
95 let doc = parse_document(content);
96 assert_eq!(doc.frontmatter.title, "T");
97 assert!(
98 doc.raw_markdown.contains("first para"),
99 "body before the second rule was eaten: {:?}",
100 doc.raw_markdown
101 );
102 assert!(doc.raw_markdown.contains("second para"));
103 }
104}