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