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