🦠 The Definitive Gemini Protocol Toolkit
gemini gemini-protocol gemtext parser zero-dependency toolkit ast converter html markdown cli networking

fix(ast): preserve newline structure at end of gemtext

fuwn.net fe03915e 49898e1c

verified
+20 -8
+15 -3
src/ast/container.rs
··· 82 82 )); 83 83 } 84 84 85 + if source.chars().last().map_or(false, |c| c == '\n') { 86 + if let Some(last) = ast.last() { 87 + if !matches!(last, Node::Whitespace) { 88 + ast.push(Node::Whitespace); 89 + } 90 + } 91 + } 92 + 85 93 Self { inner: ast } 86 94 } 87 95 ··· 95 103 /// // the original Gemtext. 96 104 /// assert_eq!( 97 105 /// germ::ast::Ast::from_nodes( 98 - /// germ::gemini_to_ast!("=> / Home\n").inner().to_vec() 106 + /// germ::gemini_to_ast!("=> / Home").inner().to_vec() 99 107 /// ) 100 108 /// .to_gemtext(), 101 - /// "=> / Home\n" 109 + /// "=> / Home" 102 110 /// ); 103 111 /// ``` 104 112 #[must_use] ··· 143 151 )), 144 152 Node::Whitespace => gemtext.push('\n'), 145 153 } 154 + } 155 + 156 + if gemtext.ends_with('\n') && !gemtext.ends_with("\n\n") { 157 + gemtext.pop(); 146 158 } 147 159 148 160 gemtext ··· 279 291 280 292 break; 281 293 } 282 - // This as a catchall, it does a number of things. 294 + // This as a catchall. It does a number of things. 283 295 _ => { 284 296 if *in_preformatted { 285 297 // If we are in a preformatted line context, add the line to the
+1 -1
src/ast/macros.rs
··· 26 26 /// germ::gemini_to_ast!("=> / A link!").to_gemtext(), 27 27 /// // `to_gemtext` appends a newline to all responses, so let's make sure we 28 28 /// // account for that. 29 - /// format!("{}\n", "=> / A link!"), 29 + /// "=> / A link!", 30 30 /// ); 31 31 #[macro_export] 32 32 macro_rules! gemini_to_ast {
+4 -4
tests/ast.rs
··· 88 88 Ast::from_string(EXAMPLE_GEMTEXT).to_gemtext(), 89 89 // `to_gemtext` appends a newline to all responses, so let's make sure we 90 90 // account for that. 91 - format!("{}\n", EXAMPLE_GEMTEXT), 91 + EXAMPLE_GEMTEXT 92 92 ); 93 93 } 94 94 ··· 98 98 germ::gemini_to_ast!(EXAMPLE_GEMTEXT).to_gemtext(), 99 99 // `to_gemtext` appends a newline to all responses, so let's make sure we 100 100 // account for that. 101 - format!("{}\n", EXAMPLE_GEMTEXT), 101 + EXAMPLE_GEMTEXT 102 102 ); 103 103 } 104 104 105 105 #[test] 106 106 fn gemtext_to_ast_then_node_to_ast_to_gemtext() { 107 107 assert_eq!( 108 - Ast::from_nodes(germ::gemini_to_ast!("=> / Home\n").inner().to_vec()) 108 + Ast::from_nodes(germ::gemini_to_ast!("=> / Home").inner().to_vec()) 109 109 .to_gemtext(), 110 - "=> / Home\n" 110 + "=> / Home" 111 111 ); 112 112 } 113 113 }