1use nom::IResult;
2use std::cell::RefCell;
3use std::collections::HashMap;
4use std::rc::Rc;
5
6type ElementMapFn<ELT> = Rc<RefCell<Box<dyn FnMut(ELT) -> ELT>>>;
8
9type ElementFlatMapFn<ELT> = Rc<RefCell<Box<dyn FnMut(ELT) -> Vec<ELT>>>>;
11
12type CustomBlockParserFn =
14 Rc<RefCell<Box<dyn for<'a> FnMut(&'a str) -> IResult<&'a str, Vec<crate::ast::Block>>>>>;
15
16type CustomInlineParserFn =
18 Rc<RefCell<Box<dyn for<'a> FnMut(&'a str) -> IResult<&'a str, Vec<crate::ast::Inline>>>>>;
19
20pub const DEFAULT_MAX_NESTING_DEPTH: usize = 32;
22
23#[derive(Clone)]
25pub enum ElementBehavior<ELT> {
26 Parse,
28
29 Ignore,
32
33 Skip,
35
36 Map(ElementMapFn<ELT>),
38
39 FlatMap(ElementFlatMapFn<ELT>),
41}
42
43#[derive(Clone)]
45pub struct MarkdownParserConfig {
46 pub(crate) allow_no_space_in_headings: bool,
48
49 pub(crate) html_entities_map: HashMap<String, &'static entities::Entity>,
51
52 pub(crate) max_nesting_depth: usize,
55
56 pub(crate) block_blockquote_behavior: ElementBehavior<crate::ast::Block>,
58
59 pub(crate) block_github_alert_behavior: ElementBehavior<crate::ast::Block>,
61
62 pub(crate) block_heading_v1_behavior: ElementBehavior<crate::ast::Block>,
64
65 pub(crate) block_heading_v2_behavior: ElementBehavior<crate::ast::Block>,
67
68 pub(crate) block_thematic_break_behavior: ElementBehavior<crate::ast::Block>,
70
71 pub(crate) block_list_behavior: ElementBehavior<crate::ast::Block>,
73
74 pub(crate) block_code_block_behavior: ElementBehavior<crate::ast::Block>,
76
77 pub(crate) block_html_block_behavior: ElementBehavior<crate::ast::Block>,
79
80 pub(crate) block_footnote_definition_behavior: ElementBehavior<crate::ast::Block>,
82
83 pub(crate) block_link_definition_behavior: ElementBehavior<crate::ast::Block>,
85
86 pub(crate) block_table_behavior: ElementBehavior<crate::ast::Block>,
88
89 pub(crate) block_paragraph_behavior: ElementBehavior<crate::ast::Block>,
91
92 pub(crate) inline_autolink_behavior: ElementBehavior<crate::ast::Inline>,
94
95 pub(crate) inline_link_behavior: ElementBehavior<crate::ast::Inline>,
97
98 pub(crate) inline_footnote_reference_behavior: ElementBehavior<crate::ast::Inline>,
100
101 pub(crate) inline_reference_link_behavior: ElementBehavior<crate::ast::Inline>,
103
104 pub(crate) inline_hard_newline_behavior: ElementBehavior<crate::ast::Inline>,
106
107 pub(crate) inline_image_behavior: ElementBehavior<crate::ast::Inline>,
109
110 pub(crate) inline_code_span_behavior: ElementBehavior<crate::ast::Inline>,
112
113 pub(crate) inline_emphasis_behavior: ElementBehavior<crate::ast::Inline>,
115
116 pub(crate) inline_strikethrough_behavior: ElementBehavior<crate::ast::Inline>,
118
119 pub(crate) inline_text_behavior: ElementBehavior<crate::ast::Inline>,
121
122 pub(crate) custom_block_parser: Option<CustomBlockParserFn>,
124
125 pub(crate) custom_inline_parser: Option<CustomInlineParserFn>,
127}
128
129impl Default for MarkdownParserConfig {
130 fn default() -> Self {
131 Self {
132 allow_no_space_in_headings: false,
133 html_entities_map: Self::make_html_entities_map(),
134 max_nesting_depth: DEFAULT_MAX_NESTING_DEPTH,
135 block_blockquote_behavior: ElementBehavior::Parse,
136 block_github_alert_behavior: ElementBehavior::Parse,
137 block_heading_v1_behavior: ElementBehavior::Parse,
138 block_heading_v2_behavior: ElementBehavior::Parse,
139 block_thematic_break_behavior: ElementBehavior::Parse,
140 block_list_behavior: ElementBehavior::Parse,
141 block_code_block_behavior: ElementBehavior::Parse,
142 block_html_block_behavior: ElementBehavior::Parse,
143 block_footnote_definition_behavior: ElementBehavior::Parse,
144 block_link_definition_behavior: ElementBehavior::Parse,
145 block_table_behavior: ElementBehavior::Parse,
146 block_paragraph_behavior: ElementBehavior::Parse,
147 inline_autolink_behavior: ElementBehavior::Parse,
148 inline_link_behavior: ElementBehavior::Parse,
149 inline_footnote_reference_behavior: ElementBehavior::Parse,
150 inline_reference_link_behavior: ElementBehavior::Parse,
151 inline_hard_newline_behavior: ElementBehavior::Parse,
152 inline_image_behavior: ElementBehavior::Parse,
153 inline_code_span_behavior: ElementBehavior::Parse,
154 inline_emphasis_behavior: ElementBehavior::Parse,
155 inline_strikethrough_behavior: ElementBehavior::Parse,
156 inline_text_behavior: ElementBehavior::Parse,
157 custom_block_parser: None,
158 custom_inline_parser: None,
159 }
160 }
161}
162
163impl MarkdownParserConfig {
164 fn make_html_entities_map() -> HashMap<String, &'static entities::Entity> {
165 let mut map = HashMap::new();
166 for entity in entities::ENTITIES.iter() {
167 map.insert(entity.entity.to_string(), entity);
168 }
169 map
170 }
171
172 pub fn with_allow_no_space_in_headings(self) -> Self {
174 Self {
175 allow_no_space_in_headings: true,
176 ..self
177 }
178 }
179
180 pub fn with_max_nesting_depth(self, depth: usize) -> Self {
191 Self {
192 max_nesting_depth: depth,
193 ..self
194 }
195 }
196
197 pub fn with_html_entities_map(
199 self,
200 html_entities_map: HashMap<String, &'static entities::Entity>,
201 ) -> Self {
202 Self {
203 html_entities_map,
204 ..self
205 }
206 }
207
208 pub fn with_block_blockquote_behavior(
210 self,
211 behavior: ElementBehavior<crate::ast::Block>,
212 ) -> Self {
213 Self {
214 block_blockquote_behavior: behavior,
215 ..self
216 }
217 }
218
219 pub fn with_block_github_alert_behavior(
221 self,
222 behavior: ElementBehavior<crate::ast::Block>,
223 ) -> Self {
224 Self {
225 block_github_alert_behavior: behavior,
226 ..self
227 }
228 }
229
230 pub fn with_block_heading_v1_behavior(
232 self,
233 behavior: ElementBehavior<crate::ast::Block>,
234 ) -> Self {
235 Self {
236 block_heading_v1_behavior: behavior,
237 ..self
238 }
239 }
240
241 pub fn with_block_heading_v2_behavior(
243 self,
244 behavior: ElementBehavior<crate::ast::Block>,
245 ) -> Self {
246 Self {
247 block_heading_v2_behavior: behavior,
248 ..self
249 }
250 }
251
252 pub fn with_block_thematic_break_behavior(
254 self,
255 behavior: ElementBehavior<crate::ast::Block>,
256 ) -> Self {
257 Self {
258 block_thematic_break_behavior: behavior,
259 ..self
260 }
261 }
262
263 pub fn with_block_list_behavior(self, behavior: ElementBehavior<crate::ast::Block>) -> Self {
265 Self {
266 block_list_behavior: behavior,
267 ..self
268 }
269 }
270
271 pub fn with_block_code_block_behavior(
273 self,
274 behavior: ElementBehavior<crate::ast::Block>,
275 ) -> Self {
276 Self {
277 block_code_block_behavior: behavior,
278 ..self
279 }
280 }
281
282 pub fn with_block_html_block_behavior(
284 self,
285 behavior: ElementBehavior<crate::ast::Block>,
286 ) -> Self {
287 Self {
288 block_html_block_behavior: behavior,
289 ..self
290 }
291 }
292
293 pub fn with_block_footnote_definition_behavior(
295 self,
296 behavior: ElementBehavior<crate::ast::Block>,
297 ) -> Self {
298 Self {
299 block_footnote_definition_behavior: behavior,
300 ..self
301 }
302 }
303
304 pub fn with_block_link_definition_behavior(
306 self,
307 behavior: ElementBehavior<crate::ast::Block>,
308 ) -> Self {
309 Self {
310 block_link_definition_behavior: behavior,
311 ..self
312 }
313 }
314
315 pub fn with_block_table_behavior(self, behavior: ElementBehavior<crate::ast::Block>) -> Self {
317 Self {
318 block_table_behavior: behavior,
319 ..self
320 }
321 }
322
323 pub fn with_block_paragraph_behavior(
325 self,
326 behavior: ElementBehavior<crate::ast::Block>,
327 ) -> Self {
328 Self {
329 block_paragraph_behavior: behavior,
330 ..self
331 }
332 }
333
334 pub fn with_inline_autolink_behavior(
336 self,
337 behavior: ElementBehavior<crate::ast::Inline>,
338 ) -> Self {
339 Self {
340 inline_autolink_behavior: behavior,
341 ..self
342 }
343 }
344
345 pub fn with_inline_link_behavior(self, behavior: ElementBehavior<crate::ast::Inline>) -> Self {
347 Self {
348 inline_link_behavior: behavior,
349 ..self
350 }
351 }
352
353 pub fn with_inline_footnote_reference_behavior(
355 self,
356 behavior: ElementBehavior<crate::ast::Inline>,
357 ) -> Self {
358 Self {
359 inline_footnote_reference_behavior: behavior,
360 ..self
361 }
362 }
363
364 pub fn with_inline_reference_link_behavior(
366 self,
367 behavior: ElementBehavior<crate::ast::Inline>,
368 ) -> Self {
369 Self {
370 inline_reference_link_behavior: behavior,
371 ..self
372 }
373 }
374
375 pub fn with_inline_hard_newline_behavior(
377 self,
378 behavior: ElementBehavior<crate::ast::Inline>,
379 ) -> Self {
380 Self {
381 inline_hard_newline_behavior: behavior,
382 ..self
383 }
384 }
385
386 pub fn with_inline_image_behavior(self, behavior: ElementBehavior<crate::ast::Inline>) -> Self {
388 Self {
389 inline_image_behavior: behavior,
390 ..self
391 }
392 }
393
394 pub fn with_inline_code_span_behavior(
396 self,
397 behavior: ElementBehavior<crate::ast::Inline>,
398 ) -> Self {
399 Self {
400 inline_code_span_behavior: behavior,
401 ..self
402 }
403 }
404
405 pub fn with_inline_emphasis_behavior(
407 self,
408 behavior: ElementBehavior<crate::ast::Inline>,
409 ) -> Self {
410 Self {
411 inline_emphasis_behavior: behavior,
412 ..self
413 }
414 }
415
416 pub fn with_inline_strikethrough_behavior(
418 self,
419 behavior: ElementBehavior<crate::ast::Inline>,
420 ) -> Self {
421 Self {
422 inline_strikethrough_behavior: behavior,
423 ..self
424 }
425 }
426
427 pub fn with_inline_text_behavior(self, behavior: ElementBehavior<crate::ast::Inline>) -> Self {
429 Self {
430 inline_text_behavior: behavior,
431 ..self
432 }
433 }
434
435 pub fn with_custom_block_parser(self, parser: CustomBlockParserFn) -> Self {
437 Self {
438 custom_block_parser: Some(parser),
439 ..self
440 }
441 }
442
443 pub fn with_custom_inline_parser(self, parser: CustomInlineParserFn) -> Self {
445 Self {
446 custom_inline_parser: Some(parser),
447 ..self
448 }
449 }
450}