mrml/lib.rs
1#![doc = include_str!("../readme.md")]
2
3pub mod comment;
4pub mod conditional_comment;
5pub mod mj_accordion;
6pub mod mj_accordion_element;
7pub mod mj_accordion_text;
8pub mod mj_accordion_title;
9pub mod mj_attributes;
10pub mod mj_attributes_all;
11pub mod mj_attributes_class;
12pub mod mj_attributes_element;
13pub mod mj_body;
14pub mod mj_breakpoint;
15pub mod mj_button;
16pub mod mj_carousel;
17pub mod mj_carousel_image;
18pub mod mj_column;
19pub mod mj_divider;
20pub mod mj_font;
21pub mod mj_group;
22pub mod mj_head;
23pub mod mj_hero;
24pub mod mj_image;
25pub mod mj_include;
26pub mod mj_navbar;
27pub mod mj_navbar_link;
28pub mod mj_preview;
29pub mod mj_raw;
30pub mod mj_section;
31pub mod mj_social;
32pub mod mj_social_element;
33pub mod mj_spacer;
34pub mod mj_style;
35pub mod mj_table;
36pub mod mj_text;
37pub mod mj_title;
38pub mod mj_wrapper;
39pub mod mjml;
40pub mod node;
41pub mod prelude;
42pub mod text;
43
44// Only used to ignore the comments at the root level
45#[cfg(feature = "parse")]
46mod root;
47
48mod helper;
49
50#[cfg(feature = "parse")]
51/// Function to parse a raw mjml template with some parsing
52/// [options](crate::prelude::parser::ParserOptions). This function is just an
53/// alias to [the `Mjml::parse_with_options` function](crate::mjml::Mjml).
54///
55/// You can specify the kind of loader mrml needs to use for loading the content
56/// of [`mj-include`](crate::mj_include) elements.
57///
58/// You can take a look at the available loaders [here](crate::prelude::parser).
59///
60/// ```rust
61/// use mrml::prelude::parser::ParserOptions;
62/// use mrml::prelude::parser::memory_loader::MemoryIncludeLoader;
63///
64/// let options = ParserOptions {
65/// include_loader: Box::new(MemoryIncludeLoader::default()),
66/// };
67/// match mrml::parse_with_options("<mjml><mj-head /><mj-body /></mjml>", &options) {
68/// Ok(_) => println!("Success!"),
69/// Err(err) => eprintln!("Something went wrong: {err:?}"),
70/// }
71/// ```
72pub fn parse_with_options<T: AsRef<str>>(
73 input: T,
74 opts: &crate::prelude::parser::ParserOptions,
75) -> Result<crate::prelude::parser::ParseOutput<mjml::Mjml>, prelude::parser::Error> {
76 let root = crate::root::Root::parse_with_options(input, opts)?;
77 Ok(crate::prelude::parser::ParseOutput {
78 element: root
79 .element
80 .into_mjml()
81 .ok_or(prelude::parser::Error::NoRootNode)?,
82 warnings: root.warnings,
83 })
84}
85
86#[cfg(all(feature = "parse", feature = "async"))]
87/// Function to parse asynchronously a raw mjml template with some parsing
88/// [options](crate::prelude::parser::AsyncParserOptions). This function is just
89/// an alias to [the `Mjml::async_parse_with_options`
90/// function](crate::mjml::Mjml).
91///
92/// You can specify the kind of loader mrml needs to use for loading the content
93/// of [`mj-include`](crate::mj_include) elements.
94///
95/// You can take a look at the available loaders [here](crate::prelude::parse).
96///
97/// ```rust
98/// # tokio_test::block_on(async {
99/// use mrml::prelude::parser::AsyncParserOptions;
100/// use mrml::prelude::parser::memory_loader::MemoryIncludeLoader;
101///
102/// let options = std::sync::Arc::new(AsyncParserOptions {
103/// include_loader: Box::new(MemoryIncludeLoader::default()),
104/// });
105/// match mrml::async_parse_with_options("<mjml><mj-head /><mj-body /></mjml>", options).await {
106/// Ok(_) => println!("Success!"),
107/// Err(err) => eprintln!("Something went wrong: {err:?}"),
108/// }
109/// # })
110/// ```
111pub async fn async_parse_with_options<T: AsRef<str>>(
112 input: T,
113 opts: std::sync::Arc<crate::prelude::parser::AsyncParserOptions>,
114) -> Result<crate::prelude::parser::ParseOutput<mjml::Mjml>, prelude::parser::Error> {
115 let root = crate::root::Root::async_parse_with_options(input, opts).await?;
116 Ok(crate::prelude::parser::ParseOutput {
117 element: root
118 .element
119 .into_mjml()
120 .ok_or(prelude::parser::Error::NoRootNode)?,
121 warnings: root.warnings,
122 })
123}
124
125#[cfg(feature = "parse")]
126/// Function to parse a raw mjml template using the default parsing
127/// [options](crate::prelude::parser::ParserOptions).
128///
129/// ```rust
130/// match mrml::parse("<mjml><mj-head /><mj-body /></mjml>") {
131/// Ok(_) => println!("Success!"),
132/// Err(err) => eprintln!("Something went wrong: {err:?}"),
133/// }
134/// ```
135pub fn parse<T: AsRef<str>>(
136 input: T,
137) -> Result<prelude::parser::ParseOutput<mjml::Mjml>, prelude::parser::Error> {
138 let opts = crate::prelude::parser::ParserOptions::default();
139 parse_with_options(input, &opts)
140}
141
142#[cfg(all(feature = "parse", feature = "async"))]
143/// Function to parse a raw mjml template using the default parsing
144/// [options](crate::prelude::parser::ParserOptions).
145///
146/// ```rust
147/// # tokio_test::block_on(async {
148/// match mrml::async_parse("<mjml><mj-head /><mj-body /></mjml>").await {
149/// Ok(_) => println!("Success!"),
150/// Err(err) => eprintln!("Something went wrong: {err:?}"),
151/// }
152/// # })
153/// ```
154pub async fn async_parse<T: AsRef<str>>(
155 input: T,
156) -> Result<crate::prelude::parser::ParseOutput<mjml::Mjml>, prelude::parser::Error> {
157 let opts = std::sync::Arc::new(crate::prelude::parser::AsyncParserOptions::default());
158 async_parse_with_options(input, opts).await
159}
160
161#[cfg(all(test, feature = "parse"))]
162mod tests {
163 #[test]
164 fn parse_simple() {
165 let _ = crate::parse("<mjml><mj-head /><mj-body /></mjml>");
166 }
167
168 #[test]
169 fn parse_with_options() {
170 let _ =
171 crate::parse_with_options("<mjml><mj-head /><mj-body /></mjml>", &Default::default());
172 }
173}