markdown_ppp/parser/
config.rs

1use nom::IResult;
2use std::cell::RefCell;
3use std::collections::HashMap;
4use std::rc::Rc;
5
6/// Function type for mapping elements.
7type ElementMapFn<ELT> = Rc<RefCell<Box<dyn FnMut(ELT) -> ELT>>>;
8
9/// Function type for mapping elements.
10type ElementFlatMapFn<ELT> = Rc<RefCell<Box<dyn FnMut(ELT) -> Vec<ELT>>>>;
11
12/// Function type for custom block parsers.
13type CustomBlockParserFn =
14    Rc<RefCell<Box<dyn for<'a> FnMut(&'a str) -> IResult<&'a str, Vec<crate::ast::Block>>>>>;
15
16/// Function type for custom inline parsers.
17type CustomInlineParserFn =
18    Rc<RefCell<Box<dyn for<'a> FnMut(&'a str) -> IResult<&'a str, Vec<crate::ast::Inline>>>>>;
19
20/// Behavior of the parser when encountering certain elements.
21#[derive(Clone)]
22pub enum ElementBehavior<ELT> {
23    /// The parser will parse the element normally.
24    Parse,
25
26    /// The parser will ignore the element and not parse it. In this case, alternative
27    /// parsers will be tried.
28    Ignore,
29
30    /// Parse element but do not include it in the output.
31    Skip,
32
33    /// Parse the element and apply a custom function to it.
34    Map(ElementMapFn<ELT>),
35
36    /// Parse the element and apply a custom function to it which returns an array of elements.
37    FlatMap(ElementFlatMapFn<ELT>),
38}
39
40/// A configuration for the Markdown parser.
41#[derive(Clone)]
42pub struct MarkdownParserConfig {
43    /// If true, the parser will allow headings without a space after the hash marks.
44    pub(crate) allow_no_space_in_headings: bool,
45
46    /// A map of HTML entities to their corresponding `Entity` structs.
47    pub(crate) html_entities_map: HashMap<String, &'static entities::Entity>,
48
49    /// The behavior of the parser when encountering blockquotes.
50    pub(crate) block_blockquote_behavior: ElementBehavior<crate::ast::Block>,
51
52    /// The behavior of the parser when encountering headings in style 1 (e.g., `# Heading`).
53    pub(crate) block_heading_v1_behavior: ElementBehavior<crate::ast::Block>,
54
55    /// The behavior of the parser when encountering headings in style 2 (e.g., `Heading\n===`).
56    pub(crate) block_heading_v2_behavior: ElementBehavior<crate::ast::Block>,
57
58    /// The behavior of the parser when encountering thematic breaks (e.g., `---`).
59    pub(crate) block_thematic_break_behavior: ElementBehavior<crate::ast::Block>,
60
61    /// The behavior of the parser when encountering lists.
62    pub(crate) block_list_behavior: ElementBehavior<crate::ast::Block>,
63
64    /// The behavior of the parser when encountering code blocks.
65    pub(crate) block_code_block_behavior: ElementBehavior<crate::ast::Block>,
66
67    /// The behavior of the parser when encountering HTML blocks.
68    pub(crate) block_html_block_behavior: ElementBehavior<crate::ast::Block>,
69
70    /// The behavior of the parser when encountering footnote definitions.
71    pub(crate) block_footnote_definition_behavior: ElementBehavior<crate::ast::Block>,
72
73    /// The behavior of the parser when encountering link definitions.
74    pub(crate) block_link_definition_behavior: ElementBehavior<crate::ast::Block>,
75
76    /// The behavior of the parser when encountering tables.
77    pub(crate) block_table_behavior: ElementBehavior<crate::ast::Block>,
78
79    /// The behavior of the parser when encountering block paragraphs.
80    pub(crate) block_paragraph_behavior: ElementBehavior<crate::ast::Block>,
81
82    /// The behavior of the parser when encountering inline autolinks.
83    pub(crate) inline_autolink_behavior: ElementBehavior<crate::ast::Inline>,
84
85    /// The behavior of the parser when encountering inline links.
86    pub(crate) inline_link_behavior: ElementBehavior<crate::ast::Inline>,
87
88    /// The behavior of the parser when encountering inline footnote references.
89    pub(crate) inline_footnote_reference_behavior: ElementBehavior<crate::ast::Inline>,
90
91    /// The behavior of the parser when encountering inline reference links.
92    pub(crate) inline_reference_link_behavior: ElementBehavior<crate::ast::Inline>,
93
94    /// The behavior of the parser when encountering inline hard newlines.
95    pub(crate) inline_hard_newline_behavior: ElementBehavior<crate::ast::Inline>,
96
97    /// The behavior of the parser when encountering inline images.
98    pub(crate) inline_image_behavior: ElementBehavior<crate::ast::Inline>,
99
100    /// The behavior of the parser when encountering inline code spans.
101    pub(crate) inline_code_span_behavior: ElementBehavior<crate::ast::Inline>,
102
103    /// The behavior of the parser when encountering inline emphasis.
104    pub(crate) inline_emphasis_behavior: ElementBehavior<crate::ast::Inline>,
105
106    /// The behavior of the parser when encountering inline strikethrough.
107    pub(crate) inline_strikethrough_behavior: ElementBehavior<crate::ast::Inline>,
108
109    /// The behavior of the parser when encountering inline text.
110    pub(crate) inline_text_behavior: ElementBehavior<crate::ast::Inline>,
111
112    /// A custom parser for blocks. This is a function that takes a string and returns a `Block`.
113    pub(crate) custom_block_parser: Option<CustomBlockParserFn>,
114
115    /// A custom parser for inlines. This is a function that takes a string and returns a `Inline`.
116    pub(crate) custom_inline_parser: Option<CustomInlineParserFn>,
117}
118
119impl Default for MarkdownParserConfig {
120    fn default() -> Self {
121        Self {
122            allow_no_space_in_headings: false,
123            html_entities_map: Self::make_html_entities_map(),
124            block_blockquote_behavior: ElementBehavior::Parse,
125            block_heading_v1_behavior: ElementBehavior::Parse,
126            block_heading_v2_behavior: ElementBehavior::Parse,
127            block_thematic_break_behavior: ElementBehavior::Parse,
128            block_list_behavior: ElementBehavior::Parse,
129            block_code_block_behavior: ElementBehavior::Parse,
130            block_html_block_behavior: ElementBehavior::Parse,
131            block_footnote_definition_behavior: ElementBehavior::Parse,
132            block_link_definition_behavior: ElementBehavior::Parse,
133            block_table_behavior: ElementBehavior::Parse,
134            block_paragraph_behavior: ElementBehavior::Parse,
135            inline_autolink_behavior: ElementBehavior::Parse,
136            inline_link_behavior: ElementBehavior::Parse,
137            inline_footnote_reference_behavior: ElementBehavior::Parse,
138            inline_reference_link_behavior: ElementBehavior::Parse,
139            inline_hard_newline_behavior: ElementBehavior::Parse,
140            inline_image_behavior: ElementBehavior::Parse,
141            inline_code_span_behavior: ElementBehavior::Parse,
142            inline_emphasis_behavior: ElementBehavior::Parse,
143            inline_strikethrough_behavior: ElementBehavior::Parse,
144            inline_text_behavior: ElementBehavior::Parse,
145            custom_block_parser: None,
146            custom_inline_parser: None,
147        }
148    }
149}
150
151impl MarkdownParserConfig {
152    fn make_html_entities_map() -> HashMap<String, &'static entities::Entity> {
153        let mut map = HashMap::new();
154        for entity in entities::ENTITIES.iter() {
155            map.insert(entity.entity.to_string(), entity);
156        }
157        map
158    }
159
160    /// Enable the parser to allow headings without a space after the hash marks.
161    pub fn with_allow_no_space_in_headings(self) -> Self {
162        Self {
163            allow_no_space_in_headings: true,
164            ..self
165        }
166    }
167
168    /// Set a custom map of HTML entities.
169    pub fn with_html_entities_map(
170        self,
171        html_entities_map: HashMap<String, &'static entities::Entity>,
172    ) -> Self {
173        Self {
174            html_entities_map,
175            ..self
176        }
177    }
178
179    /// Set the behavior of the parser when encountering blockquotes.
180    pub fn with_block_blockquote_behavior(
181        self,
182        behavior: ElementBehavior<crate::ast::Block>,
183    ) -> Self {
184        Self {
185            block_blockquote_behavior: behavior,
186            ..self
187        }
188    }
189
190    /// Set the behavior of the parser when encountering headings in style 1 (e.g., `# Heading`).
191    pub fn with_block_heading_v1_behavior(
192        self,
193        behavior: ElementBehavior<crate::ast::Block>,
194    ) -> Self {
195        Self {
196            block_heading_v1_behavior: behavior,
197            ..self
198        }
199    }
200
201    /// Set the behavior of the parser when encountering headings in style 2 (e.g., `Heading\n===`).
202    pub fn with_block_heading_v2_behavior(
203        self,
204        behavior: ElementBehavior<crate::ast::Block>,
205    ) -> Self {
206        Self {
207            block_heading_v2_behavior: behavior,
208            ..self
209        }
210    }
211
212    /// Set the behavior of the parser when encountering thematic breaks (e.g., `---`).
213    pub fn with_block_thematic_break_behavior(
214        self,
215        behavior: ElementBehavior<crate::ast::Block>,
216    ) -> Self {
217        Self {
218            block_thematic_break_behavior: behavior,
219            ..self
220        }
221    }
222
223    /// Set the behavior of the parser when encountering lists.
224    pub fn with_block_list_behavior(self, behavior: ElementBehavior<crate::ast::Block>) -> Self {
225        Self {
226            block_list_behavior: behavior,
227            ..self
228        }
229    }
230
231    /// Set the behavior of the parser when encountering code blocks.
232    pub fn with_block_code_block_behavior(
233        self,
234        behavior: ElementBehavior<crate::ast::Block>,
235    ) -> Self {
236        Self {
237            block_code_block_behavior: behavior,
238            ..self
239        }
240    }
241
242    /// Set the behavior of the parser when encountering HTML blocks.
243    pub fn with_block_html_block_behavior(
244        self,
245        behavior: ElementBehavior<crate::ast::Block>,
246    ) -> Self {
247        Self {
248            block_html_block_behavior: behavior,
249            ..self
250        }
251    }
252
253    /// Set the behavior of the parser when encountering footnote definitions.
254    pub fn with_block_footnote_definition_behavior(
255        self,
256        behavior: ElementBehavior<crate::ast::Block>,
257    ) -> Self {
258        Self {
259            block_footnote_definition_behavior: behavior,
260            ..self
261        }
262    }
263
264    /// Set the behavior of the parser when encountering link definitions.
265    pub fn with_block_link_definition_behavior(
266        self,
267        behavior: ElementBehavior<crate::ast::Block>,
268    ) -> Self {
269        Self {
270            block_link_definition_behavior: behavior,
271            ..self
272        }
273    }
274
275    /// Set the behavior of the parser when encountering tables.
276    pub fn with_block_table_behavior(self, behavior: ElementBehavior<crate::ast::Block>) -> Self {
277        Self {
278            block_table_behavior: behavior,
279            ..self
280        }
281    }
282
283    /// Set the behavior of the parser when encountering block paragraphs.
284    pub fn with_block_paragraph_behavior(
285        self,
286        behavior: ElementBehavior<crate::ast::Block>,
287    ) -> Self {
288        Self {
289            block_paragraph_behavior: behavior,
290            ..self
291        }
292    }
293
294    /// Set the behavior of the parser when encountering inline autolinks.
295    pub fn with_inline_autolink_behavior(
296        self,
297        behavior: ElementBehavior<crate::ast::Inline>,
298    ) -> Self {
299        Self {
300            inline_autolink_behavior: behavior,
301            ..self
302        }
303    }
304
305    /// Set the behavior of the parser when encountering inline links.
306    pub fn with_inline_link_behavior(self, behavior: ElementBehavior<crate::ast::Inline>) -> Self {
307        Self {
308            inline_link_behavior: behavior,
309            ..self
310        }
311    }
312
313    /// Set the behavior of the parser when encountering inline footnote references.
314    pub fn with_inline_footnote_reference_behavior(
315        self,
316        behavior: ElementBehavior<crate::ast::Inline>,
317    ) -> Self {
318        Self {
319            inline_footnote_reference_behavior: behavior,
320            ..self
321        }
322    }
323
324    /// Set the behavior of the parser when encountering inline reference links.
325    pub fn with_inline_reference_link_behavior(
326        self,
327        behavior: ElementBehavior<crate::ast::Inline>,
328    ) -> Self {
329        Self {
330            inline_reference_link_behavior: behavior,
331            ..self
332        }
333    }
334
335    /// Set the behavior of the parser when encountering inline hard newlines.
336    pub fn with_inline_hard_newline_behavior(
337        self,
338        behavior: ElementBehavior<crate::ast::Inline>,
339    ) -> Self {
340        Self {
341            inline_hard_newline_behavior: behavior,
342            ..self
343        }
344    }
345
346    /// Set the behavior of the parser when encountering inline images.
347    pub fn with_inline_image_behavior(self, behavior: ElementBehavior<crate::ast::Inline>) -> Self {
348        Self {
349            inline_image_behavior: behavior,
350            ..self
351        }
352    }
353
354    /// Set the behavior of the parser when encountering inline code spans.
355    pub fn with_inline_code_span_behavior(
356        self,
357        behavior: ElementBehavior<crate::ast::Inline>,
358    ) -> Self {
359        Self {
360            inline_code_span_behavior: behavior,
361            ..self
362        }
363    }
364
365    /// Set the behavior of the parser when encountering inline emphasis.
366    pub fn with_inline_emphasis_behavior(
367        self,
368        behavior: ElementBehavior<crate::ast::Inline>,
369    ) -> Self {
370        Self {
371            inline_emphasis_behavior: behavior,
372            ..self
373        }
374    }
375
376    /// Set the behavior of the parser when encountering inline strikethrough.
377    pub fn with_inline_strikethrough_behavior(
378        self,
379        behavior: ElementBehavior<crate::ast::Inline>,
380    ) -> Self {
381        Self {
382            inline_strikethrough_behavior: behavior,
383            ..self
384        }
385    }
386
387    /// Set the behavior of the parser when encountering inline text.
388    pub fn with_inline_text_behavior(self, behavior: ElementBehavior<crate::ast::Inline>) -> Self {
389        Self {
390            inline_text_behavior: behavior,
391            ..self
392        }
393    }
394
395    /// Set a custom parser for blocks.
396    pub fn with_custom_block_parser(self, parser: CustomBlockParserFn) -> Self {
397        Self {
398            custom_block_parser: Some(parser),
399            ..self
400        }
401    }
402
403    /// Set a custom parser for inlines.
404    pub fn with_custom_inline_parser(self, parser: CustomInlineParserFn) -> Self {
405        Self {
406            custom_inline_parser: Some(parser),
407            ..self
408        }
409    }
410}