cmark_writer/
options.rs

1//! CommonMark formatting options.
2//!
3//! This module provides configuration options for the CommonMark writer.
4
5/// CommonMark formatting options
6#[derive(Debug, Clone)]
7pub struct WriterOptions {
8    /// Whether to enable strict mode (strictly following CommonMark specification)
9    pub strict: bool,
10    /// Hard break mode (true uses two spaces followed by a newline, false uses backslash followed by a newline)
11    pub hard_break_spaces: bool,
12    /// Number of spaces to use for indentation levels
13    pub indent_spaces: usize,
14    /// Character to use for unordered list markers (-, +, or *)
15    pub list_marker: char,
16    /// Character to use for thematic breaks (-, *, or _)
17    pub thematic_break_char: char,
18    /// Character to use for emphasis (_, or *)
19    pub emphasis_char: char,
20    /// Character to use for strong emphasis (_, or *)
21    pub strong_char: char,
22    /// Whether to escape special characters in text content
23    pub escape_special_chars: bool,
24
25    /// Whether to enable GitHub Flavored Markdown (GFM) extensions
26    #[cfg(feature = "gfm")]
27    pub enable_gfm: bool,
28
29    /// Whether to enable GFM strikethrough syntax
30    #[cfg(feature = "gfm")]
31    pub gfm_strikethrough: bool,
32
33    /// Whether to enable GFM task lists
34    #[cfg(feature = "gfm")]
35    pub gfm_tasklists: bool,
36
37    /// Whether to enable GFM tables with alignment
38    #[cfg(feature = "gfm")]
39    pub gfm_tables: bool,
40
41    /// Whether to enable GFM autolinks without angle brackets
42    #[cfg(feature = "gfm")]
43    pub gfm_autolinks: bool,
44
45    /// List of disallowed HTML tag names in GFM mode
46    #[cfg(feature = "gfm")]
47    pub gfm_disallowed_html_tags: Vec<String>,
48}
49
50impl Default for WriterOptions {
51    fn default() -> Self {
52        Self {
53            strict: true,
54            hard_break_spaces: false,
55            indent_spaces: 4,
56            list_marker: '-',
57            thematic_break_char: '-',
58            emphasis_char: '_',
59            strong_char: '*',
60            escape_special_chars: false,
61
62            #[cfg(feature = "gfm")]
63            enable_gfm: false,
64
65            #[cfg(feature = "gfm")]
66            gfm_strikethrough: false,
67
68            #[cfg(feature = "gfm")]
69            gfm_tasklists: false,
70
71            #[cfg(feature = "gfm")]
72            gfm_tables: false,
73
74            #[cfg(feature = "gfm")]
75            gfm_autolinks: false,
76
77            #[cfg(feature = "gfm")]
78            gfm_disallowed_html_tags: vec![
79                "title".to_string(),
80                "textarea".to_string(),
81                "style".to_string(),
82                "xmp".to_string(),
83                "iframe".to_string(),
84                "noembed".to_string(),
85                "noframes".to_string(),
86                "script".to_string(),
87                "plaintext".to_string(),
88            ],
89        }
90    }
91}
92
93/// Builder for WriterOptions
94pub struct WriterOptionsBuilder {
95    options: WriterOptions,
96}
97
98impl WriterOptionsBuilder {
99    /// Create a new WriterOptionsBuilder with default options
100    pub fn new() -> Self {
101        Self {
102            options: WriterOptions::default(),
103        }
104    }
105
106    /// Set strict mode (whether to strictly follow CommonMark specification)
107    pub fn strict(mut self, strict: bool) -> Self {
108        self.options.strict = strict;
109        self
110    }
111
112    /// Set hard break mode (true uses two spaces followed by a newline, false uses backslash)
113    pub fn hard_break_spaces(mut self, hard_break_spaces: bool) -> Self {
114        self.options.hard_break_spaces = hard_break_spaces;
115        self
116    }
117
118    /// Set number of spaces for indentation
119    pub fn indent_spaces(mut self, indent_spaces: usize) -> Self {
120        self.options.indent_spaces = indent_spaces;
121        self
122    }
123
124    /// Set the marker character for unordered lists (-, +, or *)
125    pub fn list_marker(mut self, marker: char) -> Self {
126        if marker == '-' || marker == '+' || marker == '*' {
127            self.options.list_marker = marker;
128        }
129        self
130    }
131
132    /// Set whether to escape special characters in text content
133    pub fn escape_special_chars(mut self, escape: bool) -> Self {
134        self.options.escape_special_chars = escape;
135        self
136    }
137
138    /// Set the character for thematic breaks (-, *, or _)
139    pub fn thematic_break_char(mut self, char: char) -> Self {
140        if char == '-' || char == '*' || char == '_' {
141            self.options.thematic_break_char = char;
142        }
143        self
144    }
145
146    /// Set the character for emphasis (_, or *)
147    pub fn emphasis_char(mut self, char: char) -> Self {
148        if char == '_' || char == '*' {
149            self.options.emphasis_char = char;
150        }
151        self
152    }
153
154    /// Set the character for strong emphasis (_, or *)
155    pub fn strong_char(mut self, char: char) -> Self {
156        if char == '_' || char == '*' {
157            self.options.strong_char = char;
158        }
159        self
160    }
161
162    /// Enable all GitHub Flavored Markdown (GFM) extensions
163    #[cfg(feature = "gfm")]
164    pub fn enable_gfm(mut self) -> Self {
165        self.options.enable_gfm = true;
166        self.options.gfm_strikethrough = true;
167        self.options.gfm_tasklists = true;
168        self.options.gfm_tables = true;
169        self.options.gfm_autolinks = true;
170        self
171    }
172
173    /// Enable or disable GFM strikethrough syntax
174    #[cfg(feature = "gfm")]
175    pub fn gfm_strikethrough(mut self, enable: bool) -> Self {
176        self.options.gfm_strikethrough = enable;
177        if enable {
178            self.options.enable_gfm = true;
179        }
180        self
181    }
182
183    /// Enable or disable GFM task lists
184    #[cfg(feature = "gfm")]
185    pub fn gfm_tasklists(mut self, enable: bool) -> Self {
186        self.options.gfm_tasklists = enable;
187        if enable {
188            self.options.enable_gfm = true;
189        }
190        self
191    }
192
193    /// Enable or disable GFM tables with alignment
194    #[cfg(feature = "gfm")]
195    pub fn gfm_tables(mut self, enable: bool) -> Self {
196        self.options.gfm_tables = enable;
197        if enable {
198            self.options.enable_gfm = true;
199        }
200        self
201    }
202
203    /// Enable or disable GFM autolinks without angle brackets
204    #[cfg(feature = "gfm")]
205    pub fn gfm_autolinks(mut self, enable: bool) -> Self {
206        self.options.gfm_autolinks = enable;
207        if enable {
208            self.options.enable_gfm = true;
209        }
210        self
211    }
212
213    /// Set list of disallowed HTML tags in GFM mode
214    #[cfg(feature = "gfm")]
215    pub fn gfm_disallowed_html_tags(mut self, tags: Vec<String>) -> Self {
216        self.options.gfm_disallowed_html_tags = tags;
217        self
218    }
219
220    /// Build the WriterOptions
221    pub fn build(self) -> WriterOptions {
222        self.options
223    }
224}
225
226impl Default for WriterOptionsBuilder {
227    fn default() -> Self {
228        Self::new()
229    }
230}