/// ^^^^^
/// ```
- pub html_flow: bool,
+ pub(crate) html_flow: bool,
/// HTML (text).
///
/// ```markdown
/// > | a
c
/// ^^^
/// ```
- pub html_text: bool,
+ pub(crate) html_text: bool,
/// Label start (image).
///
/// ```markdown
/// > | a  d
/// ^^
/// ```
- pub label_start_image: bool,
+ pub(crate) label_start_image: bool,
/// Label start (link).
///
/// ```markdown
/// > | a [b](c) d
/// ^
/// ```
- pub label_start_link: bool,
+ pub(crate) label_start_link: bool,
/// Label end.
///
/// ```markdown
/// > | a [b](c) d
/// ^^^^
/// ```
- pub label_end: bool,
+ pub(crate) label_end: bool,
/// List items.
///
/// ```markdown
/// > | * a
/// ^^^
/// ```
- pub list_item: bool,
+ pub(crate) list_item: bool,
/// Math (flow).
///
/// ```markdown
@@ -239,14 +239,14 @@ pub struct Constructs {
/// > | $$
/// ^^
/// ```
- pub math_flow: bool,
+ pub(crate) math_flow: bool,
/// Math (text).
///
/// ```markdown
/// > | a $b$ c
/// ^^^
/// ```
- pub math_text: bool,
+ pub(crate) math_text: bool,
/// MDX: ESM.
///
/// ```markdown
@@ -257,7 +257,7 @@ pub struct Constructs {
/// > 👉 **Note**: to support ESM, you *must* pass
/// > [`mdx_esm_parse`][MdxEsmParse] in [`ParseOptions`][] too.
/// > Otherwise, ESM is treated as normal markdown.
- pub mdx_esm: bool,
+ pub(crate) mdx_esm: bool,
/// MDX: expression (flow).
///
/// ```markdown
@@ -271,7 +271,7 @@ pub struct Constructs {
/// > a programming language).
/// > Otherwise, expressions are parsed with a basic algorithm that only
/// > cares about braces.
- pub mdx_expression_flow: bool,
+ pub(crate) mdx_expression_flow: bool,
/// MDX: expression (text).
///
/// ```markdown
@@ -285,7 +285,7 @@ pub struct Constructs {
/// > a programming language).
/// > Otherwise, expressions are parsed with a basic algorithm that only
/// > cares about braces.
- pub mdx_expression_text: bool,
+ pub(crate) mdx_expression_text: bool,
/// MDX: JSX (flow).
///
/// ```markdown
@@ -302,7 +302,7 @@ pub struct Constructs {
/// > (typically, a programming language).
/// > Otherwise, expressions are parsed with a basic algorithm that only
/// > cares about braces.
- pub mdx_jsx_flow: bool,
+ pub(crate) mdx_jsx_flow: bool,
/// MDX: JSX (text).
///
/// ```markdown
@@ -319,14 +319,14 @@ pub struct Constructs {
/// > (typically, a programming language).
/// > Otherwise, expressions are parsed with a basic algorithm that only
/// > cares about braces.
- pub mdx_jsx_text: bool,
+ pub(crate) mdx_jsx_text: bool,
/// Thematic break.
///
/// ```markdown
/// > | ***
/// ^^^
/// ```
- pub thematic_break: bool,
+ pub(crate) thematic_break: bool,
}
impl Default for Constructs {
@@ -378,7 +378,7 @@ impl Default for Constructs {
}
}
-impl Constructs {
+impl ConstructsBuilder {
/// GFM.
///
/// GFM stands for **GitHub flavored markdown**.
@@ -388,15 +388,13 @@ impl Constructs {
/// For more information, see the GFM specification:
/// .
pub fn gfm() -> Self {
- Self {
- gfm_autolink_literal: true,
- gfm_footnote_definition: true,
- gfm_label_start_footnote: true,
- gfm_strikethrough: true,
- gfm_table: true,
- gfm_task_list_item: true,
- ..Self::default()
- }
+ Self::default()
+ .gfm_autolink_literal(true)
+ .gfm_footnote_definition(true)
+ .gfm_label_start_footnote(true)
+ .gfm_strikethrough(true)
+ .gfm_table(true)
+ .gfm_task_list_item(true)
}
/// MDX.
@@ -419,18 +417,29 @@ impl Constructs {
/// > Otherwise, expressions are parsed with a basic algorithm that only
/// > cares about braces.
pub fn mdx() -> Self {
- Self {
- autolink: false,
- code_indented: false,
- html_flow: false,
- html_text: false,
- mdx_esm: true,
- mdx_expression_flow: true,
- mdx_expression_text: true,
- mdx_jsx_flow: true,
- mdx_jsx_text: true,
- ..Self::default()
- }
+ Self::default()
+ .autolink(false)
+ .code_indented(false)
+ .html_flow(false)
+ .html_text(false)
+ .mdx_esm(true)
+ .mdx_expression_flow(true)
+ .mdx_expression_text(true)
+ .mdx_jsx_flow(true)
+ .mdx_jsx_text(true)
+ }
+
+ pub fn build(self) -> Constructs {
+ self.fallible_build().unwrap()
+ }
+}
+
+impl Constructs {
+ pub fn gfm() -> Self {
+ ConstructsBuilder::gfm().build()
+ }
+ pub fn mdx() -> Self {
+ ConstructsBuilder::mdx().build()
}
}
@@ -444,29 +453,28 @@ impl Constructs {
/// ## Examples
///
/// ```
-/// use markdown::CompileOptions;
+/// use markdown::{CompileOptions, CompileOptionsBuilder};
/// # fn main() {
///
/// // Use the default trait to get safe defaults:
/// let safe = CompileOptions::default();
///
/// // Live dangerously / trust the author:
-/// let danger = CompileOptions {
-/// allow_dangerous_html: true,
-/// allow_dangerous_protocol: true,
-/// ..CompileOptions::default()
-/// };
+/// let danger = CompileOptionsBuilder::default()
+/// .allow_dangerous_html(true)
+/// .allow_dangerous_protocol(true)
+/// .build();
///
/// // In French:
-/// let enFrançais = CompileOptions {
-/// gfm_footnote_label: Some("Notes de bas de page".into()),
-/// gfm_footnote_back_label: Some("Arrière".into()),
-/// ..CompileOptions::default()
-/// };
+/// let enFrançais = CompileOptionsBuilder::default()
+/// .gfm_footnote_label(Some("Notes de bas de page".into()))
+/// .gfm_footnote_back_label(Some("Arrière".into()))
+/// .build();
/// # }
/// ```
#[allow(clippy::struct_excessive_bools)]
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug, Default, derive_builder::Builder)]
+#[builder(no_std, default, pattern = "owned", build_fn(name = "fallible_build"))]
pub struct CompileOptions {
/// Whether to allow (dangerous) HTML.
///
@@ -478,7 +486,7 @@ pub struct CompileOptions {
/// ## Examples
///
/// ```
- /// use markdown::{to_html, to_html_with_options, CompileOptions, Options};
+ /// use markdown::{to_html, to_html_with_options, CompileOptionsBuilder, OptionsBuilder};
/// # fn main() -> Result<(), String> {
///
/// // `markdown-rs` is safe by default:
@@ -491,20 +499,20 @@ pub struct CompileOptions {
/// assert_eq!(
/// to_html_with_options(
/// "Hi, venus!",
- /// &Options {
- /// compile: CompileOptions {
- /// allow_dangerous_html: true,
- /// ..CompileOptions::default()
- /// },
- /// ..Options::default()
- /// }
+ /// &OptionsBuilder::default()
+ /// .compile(
+ /// CompileOptionsBuilder::default()
+ /// .allow_dangerous_html(true)
+ /// .build()
+ /// )
+ /// .build()
/// )?,
/// "Hi, venus!
"
/// );
/// # Ok(())
/// # }
/// ```
- pub allow_dangerous_html: bool,
+ pub(crate) allow_dangerous_html: bool,
/// Whether to allow dangerous protocols in links and images.
///
@@ -522,7 +530,7 @@ pub struct CompileOptions {
/// ## Examples
///
/// ```
- /// use markdown::{to_html, to_html_with_options, CompileOptions, Options};
+ /// use markdown::{to_html, to_html_with_options, CompileOptionsBuilder, OptionsBuilder};
/// # fn main() -> Result<(), String> {
///
/// // `markdown-rs` is safe by default:
@@ -535,20 +543,20 @@ pub struct CompileOptions {
/// assert_eq!(
/// to_html_with_options(
/// "
",
- /// &Options {
- /// compile: CompileOptions {
- /// allow_dangerous_protocol: true,
- /// ..CompileOptions::default()
- /// },
- /// ..Options::default()
- /// }
+ /// &OptionsBuilder::default()
+ /// .compile(
+ /// CompileOptionsBuilder::default()
+ /// .allow_dangerous_protocol(true)
+ /// .build()
+ /// )
+ /// .build()
/// )?,
/// "javascript:alert(1)
"
/// );
/// # Ok(())
/// # }
/// ```
- pub allow_dangerous_protocol: bool,
+ pub(crate) allow_dangerous_protocol: bool,
/// Default line ending to use when compiling to HTML, for line endings not
/// in `value`.
@@ -566,7 +574,7 @@ pub struct CompileOptions {
/// ## Examples
///
/// ```
- /// use markdown::{to_html, to_html_with_options, CompileOptions, LineEnding, Options};
+ /// use markdown::{to_html, to_html_with_options, CompileOptionsBuilder, LineEnding, OptionsBuilder};
/// # fn main() -> Result<(), String> {
///
/// // `markdown-rs` uses `\n` by default:
@@ -579,20 +587,20 @@ pub struct CompileOptions {
/// assert_eq!(
/// to_html_with_options(
/// "> a",
- /// &Options {
- /// compile: CompileOptions {
- /// default_line_ending: LineEnding::CarriageReturnLineFeed,
- /// ..CompileOptions::default()
- /// },
- /// ..Options::default()
- /// }
+ /// &OptionsBuilder::default()
+ /// .compile(
+ /// CompileOptionsBuilder::default()
+ /// .default_line_ending(LineEnding::CarriageReturnLineFeed)
+ /// .build()
+ /// )
+ /// .build()
/// )?,
/// "\r\na
\r\n
"
/// );
/// # Ok(())
/// # }
/// ```
- pub default_line_ending: LineEnding,
+ pub(crate) default_line_ending: LineEnding,
/// Textual label to use for the footnotes section.
///
@@ -608,7 +616,7 @@ pub struct CompileOptions {
/// ## Examples
///
/// ```
- /// use markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};
+ /// use markdown::{to_html_with_options, CompileOptionsBuilder, Options, OptionsBuilder};
/// # fn main() -> Result<(), String> {
///
/// // `"Footnotes"` is used by default:
@@ -624,20 +632,20 @@ pub struct CompileOptions {
/// assert_eq!(
/// to_html_with_options(
/// "[^a]\n\n[^a]: b",
- /// &Options {
- /// parse: ParseOptions::gfm(),
- /// compile: CompileOptions {
- /// gfm_footnote_label: Some("Notes de bas de page".into()),
- /// ..CompileOptions::gfm()
- /// }
- /// }
+ /// &OptionsBuilder::gfm()
+ /// .compile(
+ /// CompileOptionsBuilder::gfm()
+ /// .gfm_footnote_label(Some("Notes de bas de page".into()))
+ /// .build()
+ /// )
+ /// .build()
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
- pub gfm_footnote_label: Option,
+ pub(crate) gfm_footnote_label: Option,
/// HTML tag name to use for the footnote label element.
///
@@ -653,7 +661,7 @@ pub struct CompileOptions {
/// ## Examples
///
/// ```
- /// use markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};
+ /// use markdown::{to_html_with_options, CompileOptionsBuilder, Options, OptionsBuilder};
/// # fn main() -> Result<(), String> {
///
/// // `"h2"` is used by default:
@@ -669,20 +677,20 @@ pub struct CompileOptions {
/// assert_eq!(
/// to_html_with_options(
/// "[^a]\n\n[^a]: b",
- /// &Options {
- /// parse: ParseOptions::gfm(),
- /// compile: CompileOptions {
- /// gfm_footnote_label_tag_name: Some("h1".into()),
- /// ..CompileOptions::gfm()
- /// }
- /// }
+ /// &OptionsBuilder::gfm()
+ /// .compile(
+ /// CompileOptionsBuilder::gfm()
+ /// .gfm_footnote_label_tag_name(Some("h1".into()))
+ /// .build()
+ /// )
+ /// .build()
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
- pub gfm_footnote_label_tag_name: Option,
+ pub(crate) gfm_footnote_label_tag_name: Option,
/// Attributes to use on the footnote label.
///
@@ -701,7 +709,7 @@ pub struct CompileOptions {
/// ## Examples
///
/// ```
- /// use markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};
+ /// use markdown::{to_html_with_options, CompileOptionsBuilder, Options, OptionsBuilder};
/// # fn main() -> Result<(), String> {
///
/// // `"class=\"sr-only\""` is used by default:
@@ -717,20 +725,20 @@ pub struct CompileOptions {
/// assert_eq!(
/// to_html_with_options(
/// "[^a]\n\n[^a]: b",
- /// &Options {
- /// parse: ParseOptions::gfm(),
- /// compile: CompileOptions {
- /// gfm_footnote_label_attributes: Some("class=\"footnote-heading\"".into()),
- /// ..CompileOptions::gfm()
- /// }
- /// }
+ /// &OptionsBuilder::gfm()
+ /// .compile(
+ /// CompileOptionsBuilder::gfm()
+ /// .gfm_footnote_label_attributes(Some(r#"class="footnote-heading""#.into()))
+ /// .build()
+ /// )
+ /// .build()
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
- pub gfm_footnote_label_attributes: Option,
+ pub(crate) gfm_footnote_label_attributes: Option,
/// Textual label to describe the backreference back to footnote calls.
///
@@ -744,7 +752,7 @@ pub struct CompileOptions {
/// ## Examples
///
/// ```
- /// use markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};
+ /// use markdown::{to_html_with_options, CompileOptionsBuilder, Options, OptionsBuilder};
/// # fn main() -> Result<(), String> {
///
/// // `"Back to content"` is used by default:
@@ -760,20 +768,20 @@ pub struct CompileOptions {
/// assert_eq!(
/// to_html_with_options(
/// "[^a]\n\n[^a]: b",
- /// &Options {
- /// parse: ParseOptions::gfm(),
- /// compile: CompileOptions {
- /// gfm_footnote_back_label: Some("Arrière".into()),
- /// ..CompileOptions::gfm()
- /// }
- /// }
+ /// &OptionsBuilder::gfm()
+ /// .compile(
+ /// CompileOptionsBuilder::gfm()
+ /// .gfm_footnote_back_label(Some("Arrière".into()))
+ /// .build()
+ /// )
+ /// .build()
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
- pub gfm_footnote_back_label: Option,
+ pub(crate) gfm_footnote_back_label: Option,
/// Prefix to use before the `id` attribute on footnotes to prevent them
/// from *clobbering*.
@@ -800,7 +808,7 @@ pub struct CompileOptions {
/// ## Examples
///
/// ```
- /// use markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};
+ /// use markdown::{to_html_with_options, CompileOptionsBuilder, Options, OptionsBuilder};
/// # fn main() -> Result<(), String> {
///
/// // `"user-content-"` is used by default:
@@ -816,20 +824,20 @@ pub struct CompileOptions {
/// assert_eq!(
/// to_html_with_options(
/// "[^a]\n\n[^a]: b",
- /// &Options {
- /// parse: ParseOptions::gfm(),
- /// compile: CompileOptions {
- /// gfm_footnote_clobber_prefix: Some("".into()),
- /// ..CompileOptions::gfm()
- /// }
- /// }
+ /// &OptionsBuilder::gfm()
+ /// .compile(
+ /// CompileOptionsBuilder::gfm()
+ /// .gfm_footnote_clobber_prefix(Some("".into()))
+ /// .build()
+ /// )
+ /// .build()
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
- pub gfm_footnote_clobber_prefix: Option,
+ pub(crate) gfm_footnote_clobber_prefix: Option,
/// Whether to support the GFM tagfilter.
///
@@ -844,20 +852,21 @@ pub struct CompileOptions {
/// ## Examples
///
/// ```
- /// use markdown::{to_html_with_options, CompileOptions, Options, ParseOptions};
+ /// use markdown::{to_html_with_options, CompileOptionsBuilder, OptionsBuilder, ParseOptions};
/// # fn main() -> Result<(), String> {
///
/// // With `allow_dangerous_html`, `markdown-rs` passes HTML through untouched:
/// assert_eq!(
/// to_html_with_options(
/// "