mod intra; mod state; use std::ops::Deref; use bempline::{Document, Options}; use state::State; pub fn process(raw: &str) -> Markup { let mut state = State::default(); for line in raw.lines() { state.process_line(line) } state.done() } pub struct Markup { content: String, fill: Vec, } impl Markup { pub fn fill(&self) -> &[Fill] { &self.fill } pub fn content(&self) -> &str { &self.content } pub fn into_content(self) -> String { self.content } pub fn into_document(self) -> Result { let Ok(mut doc) = Document::from_str(&self.content, Options::default()) else { return Err(self.content); }; self.fill_document(&mut doc); Ok(doc) } pub fn fill_document(&self, doc: &mut Document) { for fill in &self.fill { doc.set(&fill.key, &fill.content); } } } impl Deref for Markup { type Target = String; fn deref(&self) -> &Self::Target { &self.content } } #[derive(Clone, Debug, PartialEq)] pub struct Fill { pub key: String, pub content: String, } #[cfg(test)] mod document_test { use crate::legacy::process; const BASE: &str = "test/markup"; fn test_files(test: &str) { let input_path = format!("{BASE}/{test}/input.html"); let output_path = format!("{BASE}/{test}/output.html"); let input = std::fs::read_to_string(input_path).unwrap(); let output = std::fs::read_to_string(output_path).unwrap(); let actual = process(&input).into_document().unwrap().compile(); assert_eq!(actual, output) } #[test] fn inserts_fill() { let input = "[@fill main]\nwords!\n[@fill-end]\n{main}"; let expected = "

\nwords!\n

"; let markup = process(input); let doc = markup.into_document().unwrap().compile(); assert_eq!(doc, expected) } #[test] fn fill_restores_paragraphs() { test_files("fill paragraphs"); } #[test] fn parses_complicated_fill() { test_files("complicated fill"); } }