1mod html;
76pub mod utils;
77pub use html::{
78 push_html, push_html_with_highlighting, write_html_fmt, write_html_io, AttributeMappings,
79 CodeBlockOptions, DefaultHtmlWriter, ElementOptions, HeadingOptions, HtmlConfig, HtmlError,
80 HtmlOptions, HtmlRenderer, HtmlState, HtmlWriter, HtmlWriterBase, LinkOptions, SyntectConfig,
81 SyntectConfigStyle, SyntectWriter,
82};
83pub use pulldown_html_ext_derive::html_writer;
84
85#[cfg(test)]
86mod tests_lib {
87 use super::*;
88 use pulldown_cmark::Parser;
89 use std::collections::HashMap;
90
91 #[test]
92 fn test_basic_markdown() {
93 let config = HtmlConfig::default();
94 let markdown = "# Hello\nThis is a test.";
95 let parser = Parser::new(markdown);
96 let mut output = String::new();
97
98 push_html(&mut output, parser, &config).unwrap();
99
100 assert!(output.contains("<h1"));
101 assert!(output.contains("Hello"));
102 assert!(output.contains("<p>"));
103 assert!(output.contains("This is a test."));
104 }
105
106 #[test]
107 fn test_custom_heading_classes() {
108 let mut config = HtmlConfig::default();
109 config.elements.headings.level_classes = {
110 let mut map = HashMap::new();
111 map.insert(1, "title".to_string());
112 map.insert(2, "subtitle".to_string());
113 map
114 };
115
116 let markdown = "# Main Title\n## Subtitle";
117 let parser = Parser::new(markdown);
118 let mut output = String::new();
119
120 push_html(&mut output, parser, &config).unwrap();
121
122 assert!(output.contains(r#"<h1 id="heading-1" class="title""#));
123 assert!(output.contains(r#"<h2 id="heading-2" class="subtitle""#));
124 }
125
126 #[test]
127 fn test_code_blocks() {
128 let mut config = HtmlConfig::default();
129 config.elements.code_blocks.default_language = Some("text".to_string());
130
131 let markdown = "```python\nprint('hello')\n```";
132 let parser = Parser::new(markdown);
133 let mut output = String::new();
134
135 push_html(&mut output, parser, &config).unwrap();
136 assert!(output.contains(r#"<code class="language-python">"#));
137
138 let markdown = "```\nplain text\n```";
139 let parser = Parser::new(markdown);
140 let mut output = String::new();
141
142 push_html(&mut output, parser, &config).unwrap();
143 assert!(output.contains(r#"<code class="language-text">"#));
144 }
145
146 #[test]
147 fn test_external_links() {
148 let mut config = HtmlConfig::default();
149 config.elements.links.nofollow_external = true;
150 config.elements.links.open_external_blank = true;
151
152 let markdown = "[External](https://example.com)";
153 let parser = Parser::new(markdown);
154 let mut output = String::new();
155
156 push_html(&mut output, parser, &config).unwrap();
157 assert!(output.contains(r#"rel="nofollow""#));
158 assert!(output.contains(r#"target="_blank""#));
159
160 let markdown = "[Internal](/local)";
161 let parser = Parser::new(markdown);
162 let mut output = String::new();
163
164 push_html(&mut output, parser, &config).unwrap();
165 assert!(!output.contains(r#"rel="nofollow""#));
166 assert!(!output.contains(r#"target="_blank""#));
167 }
168
169 #[test]
170 fn test_html_options() {
171 let mut config = HtmlConfig::default();
172 config.html.escape_html = true;
173 config.html.break_on_newline = false;
174 config.html.xhtml_style = true;
175
176 let markdown = "Test & test\nNew line";
177 let parser = Parser::new(markdown);
178 let mut output = String::new();
179
180 push_html(&mut output, parser, &config).unwrap();
181 assert!(output.contains("&"));
182 assert!(!output.contains("<br"));
183 }
184
185 #[test]
186 fn test_custom_parser_options() {
187 use pulldown_cmark::{Options, Parser};
188
189 let mut options = Options::empty();
190 options.insert(Options::ENABLE_STRIKETHROUGH);
191
192 let markdown = "~~strikethrough~~";
193 let parser = Parser::new_ext(markdown, options);
194 let mut output = String::new();
195 let config = HtmlConfig::default();
196
197 push_html(&mut output, parser, &config).unwrap();
198 assert!(output.contains("<del>"));
199 assert!(output.contains("</del>"));
200 }
201
202 #[test]
203 fn test_streaming_parser() {
204 let config = HtmlConfig::default();
205 let mut output = String::new();
206
207 let chunk1 = "# Title\n";
209 let chunk2 = "Paragraph 1\n";
210 let chunk3 = "* List item";
211
212 let parser1 = Parser::new(chunk1);
213 push_html(&mut output, parser1, &config).unwrap();
214
215 let parser2 = Parser::new(chunk2);
216 push_html(&mut output, parser2, &config).unwrap();
217
218 let parser3 = Parser::new(chunk3);
219 push_html(&mut output, parser3, &config).unwrap();
220
221 assert!(output.contains("<h1"));
222 assert!(output.contains("<p>"));
223 assert!(output.contains("<li>"));
224 }
225}