/// ^^^^^
/// ```
pub html_flow: bool,
/// HTML (text).
///
/// ```markdown
/// > | a
c
/// ^^^
/// ```
pub html_text: bool,
/// Label start (image).
///
/// ```markdown
/// > | a ![b](c) d
/// ^^
/// ```
pub label_start_image: bool,
/// Label start (link).
///
/// ```markdown
/// > | a [b](c) d
/// ^
/// ```
pub label_start_link: bool,
/// Label end.
///
/// ```markdown
/// > | a [b](c) d
/// ^^^^
/// ```
pub label_end: bool,
/// List items.
///
/// ```markdown
/// > | * a
/// ^^^
/// ```
pub list_item: bool,
/// Math (flow).
///
/// ```markdown
/// > | $$
/// ^^
/// > | \frac{1}{2}
/// ^^^^^^^^^^^
/// > | $$
/// ^^
/// ```
pub math_flow: bool,
/// Math (text).
///
/// ```markdown
/// > | a $b$ c
/// ^^^
/// ```
pub math_text: bool,
/// MDX: ESM.
///
/// ```markdown
/// > | import a from 'b'
/// ^^^^^^^^^^^^^^^^^
/// ```
///
/// > 👉 **Note**: you *must* pass [`options.mdx_esm_parse`][MdxEsmParse]
/// > too.
/// > Otherwise, this option has no affect.
pub mdx_esm: bool,
/// MDX: expression (flow).
///
/// ```markdown
/// > | {Math.PI}
/// ^^^^^^^^^
/// ```
///
/// > 👉 **Note**: you *can* pass
/// > [`options.mdx_expression_parse`][MdxExpressionParse]
/// > to parse expressions according to a certain grammar (typically, a
/// > programming language).
pub mdx_expression_flow: bool,
/// MDX: expression (text).
///
/// ```markdown
/// > | a {Math.PI} c
/// ^^^^^^^^^
/// ```
///
/// > 👉 **Note**: you *can* pass
/// > [`options.mdx_expression_parse`][MdxExpressionParse]
/// > to parse expressions according to a certain grammar (typically, a
/// > programming language).
pub mdx_expression_text: bool,
/// MDX: JSX (flow).
///
/// ```markdown
/// > |
/// ^^^^^^^^^^^^^
/// ```
///
/// > 👉 **Note**: you *can* pass
/// > [`options.mdx_expression_parse`][MdxExpressionParse]
/// > to parse expressions in JSX according to a certain grammar
/// > (typically, a programming language).
pub mdx_jsx_flow: bool,
/// MDX: JSX (text).
///
/// ```markdown
/// > | a c
/// ^^^^^^^^^^^^^
/// ```
///
/// > 👉 **Note**: you *can* pass
/// > [`options.mdx_expression_parse`][MdxExpressionParse]
/// > to parse expressions in JSX according to a certain grammar
/// > (typically, a programming language).
pub mdx_jsx_text: bool,
/// Thematic break.
///
/// ```markdown
/// > | ***
/// ^^^
/// ```
pub thematic_break: bool,
}
impl Default for Constructs {
/// `CommonMark`.
fn default() -> Self {
Self {
attention: true,
autolink: true,
block_quote: true,
character_escape: true,
character_reference: true,
code_indented: true,
code_fenced: true,
code_text: true,
definition: true,
frontmatter: false,
gfm_autolink_literal: false,
gfm_label_start_footnote: false,
gfm_footnote_definition: false,
gfm_strikethrough: false,
gfm_table: false,
gfm_task_list_item: false,
hard_break_escape: true,
hard_break_trailing: true,
heading_atx: true,
heading_setext: true,
html_flow: true,
html_text: true,
label_start_image: true,
label_start_link: true,
label_end: true,
list_item: true,
math_flow: false,
math_text: false,
mdx_esm: false,
mdx_expression_flow: false,
mdx_expression_text: false,
mdx_jsx_flow: false,
mdx_jsx_text: false,
thematic_break: true,
}
}
}
impl Constructs {
/// GFM.
///
///
///
/// This turns on `CommonMark` + GFM.
#[must_use]
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()
}
}
/// MDX.
///
///
///
/// This turns on `CommonMark`, turns off some conflicting constructs
/// (autolinks, code (indented), html), and turns on MDX (JSX,
/// expressions, ESM).
///
/// > 👉 **Note**: you *must* pass [`options.mdx_esm_parse`][MdxEsmParse]
/// > to support ESM.
/// > You *can* pass
/// > [`options.mdx_expression_parse`][MdxExpressionParse]
/// > to parse expressions according to a certain grammar (typically, a
/// > programming language).
#[must_use]
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()
}
}
}
/// Configuration (optional).
#[allow(clippy::struct_excessive_bools)]
pub struct Options {
// Note: when adding fields, don’t forget to add them to `fmt::Debug` below.
/// Whether to allow (dangerous) HTML.
/// The default is `false`, you can turn it on to `true` for trusted
/// content.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options};
/// # fn main() -> Result<(), String> {
///
/// // micromark is safe by default:
/// assert_eq!(
/// micromark("Hi, venus!"),
/// "Hi, <i>venus</i>!
"
/// );
///
/// // Turn `allow_dangerous_html` on to allow potentially dangerous HTML:
/// assert_eq!(
/// micromark_with_options(
/// "Hi, venus!",
/// &Options {
/// allow_dangerous_html: true,
/// ..Options::default()
/// }
/// )?,
/// "Hi, venus!
"
/// );
/// # Ok(())
/// # }
/// ```
pub allow_dangerous_html: bool,
/// Whether to allow (dangerous) protocols in links and images.
/// The default is `false`, you can turn it on to `true` for trusted
/// content.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options};
/// # fn main() -> Result<(), String> {
///
/// // micromark is safe by default:
/// assert_eq!(
/// micromark(""),
/// "javascript:alert(1)
"
/// );
///
/// // Turn `allow_dangerous_protocol` on to allow potentially dangerous protocols:
/// assert_eq!(
/// micromark_with_options(
/// "",
/// &Options {
/// allow_dangerous_protocol: true,
/// ..Options::default()
/// }
/// )?,
/// "javascript:alert(1)
"
/// );
/// # Ok(())
/// # }
/// ```
pub allow_dangerous_protocol: bool,
/// Which constructs to enable and disable.
/// The default is to follow `CommonMark`.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options, Constructs};
/// # fn main() -> Result<(), String> {
///
/// // micromark follows CommonMark by default:
/// assert_eq!(
/// micromark(" indented code?"),
/// "indented code?\n
"
/// );
///
/// // Pass `constructs` to choose what to enable and disable:
/// assert_eq!(
/// micromark_with_options(
/// " indented code?",
/// &Options {
/// constructs: Constructs {
/// code_indented: false,
/// ..Constructs::default()
/// },
/// ..Options::default()
/// }
/// )?,
/// "indented code?
"
/// );
/// # Ok(())
/// # }
/// ```
pub constructs: Constructs,
/// Default line ending to use, for line endings not in `value`.
///
/// Generally, micromark copies line endings (`\r`, `\n`, `\r\n`) in the
/// markdown document over to the compiled HTML.
/// In some cases, such as `> a`, CommonMark requires that extra line
/// endings are added: `\na
\n
`.
///
/// To create that line ending, the document is checked for the first line
/// ending that is used.
/// If there is no line ending, `default_line_ending` is used.
/// If that isn’t configured, `\n` is used.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options, LineEnding};
/// # fn main() -> Result<(), String> {
///
/// // micromark uses `\n` by default:
/// assert_eq!(
/// micromark("> a"),
/// "\na
\n
"
/// );
///
/// // Define `default_line_ending` to configure the default:
/// assert_eq!(
/// micromark_with_options(
/// "> a",
/// &Options {
/// default_line_ending: LineEnding::CarriageReturnLineFeed,
/// ..Options::default()
/// }
/// )?,
/// "\r\na
\r\n
"
/// );
/// # Ok(())
/// # }
/// ```
pub default_line_ending: LineEnding,
/// Label to use for the footnotes section.
///
/// Change it when the markdown is not in English.
/// Typically affects screen readers (change `gfm_footnote_label_attributes`
/// to make it visible).
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options, Constructs};
/// # fn main() -> Result<(), String> {
///
/// // `"Footnotes"` is used by default:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
///
/// // Pass `gfm_footnote_label` to use something else:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// gfm_footnote_label: Some("Notes de bas de page".to_string()),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
pub gfm_footnote_label: Option,
/// HTML tag to use for the footnote label.
///
/// Change it to match your document structure and play well with your CSS.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options, Constructs};
/// # fn main() -> Result<(), String> {
///
/// // `"h2"` is used by default:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
///
/// // Pass `gfm_footnote_label_tag_name` to use something else:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// gfm_footnote_label_tag_name: Some("h1".to_string()),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
pub gfm_footnote_label_tag_name: Option,
/// Attributes to use on the footnote label.
///
/// > 👉 **Note**: `id="footnote-label"` is always added, because footnote
/// > calls use it with `aria-describedby` to provide an accessible label.
///
/// A `class="sr-only"` is added by default to hide the label from sighted
/// users.
/// Change it to make the label visible, or add other classes or other
/// attributes.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options, Constructs};
/// # fn main() -> Result<(), String> {
///
/// // `"class=\"sr-only\""` is used by default:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
///
/// // Pass `gfm_footnote_label_attributes` to use something else:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// gfm_footnote_label_attributes: Some("class=\"footnote-heading\"".to_string()),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
pub gfm_footnote_label_attributes: Option,
/// Label to use from backreferences back to their footnote call.
///
/// Change it when the markdown is not in English.
/// Affects screen readers.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options, Constructs};
/// # fn main() -> Result<(), String> {
///
/// // `"Back to content"` is used by default:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
///
/// // Pass `gfm_footnote_back_label` to use something else:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// gfm_footnote_back_label: Some("Arrière".to_string()),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
pub gfm_footnote_back_label: Option,
/// Prefix to use before the `id` attribute on footnotes to prevent them
/// from *clobbering*.
///
/// DOM clobbering is this:
///
/// ```html
///
///
/// ```
///
/// The above example shows that elements are made available by browsers,
/// by their ID, on the `window` object, which is a security risk because
/// you might be expecting some other variable at that place.
/// Using a prefix solves this problem.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options, Constructs};
/// # fn main() -> Result<(), String> {
///
/// // `"user-content-"` is used by default:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
///
/// // Pass `gfm_footnote_clobber_prefix` to use something else:
/// assert_eq!(
/// micromark_with_options(
/// "[^a]\n\n[^a]: b",
/// &Options {
/// constructs: Constructs::gfm(),
/// gfm_footnote_clobber_prefix: Some("".to_string()),
/// ..Options::default()
/// }
/// )?,
/// "1
\n\n"
/// );
/// # Ok(())
/// # }
/// ```
pub gfm_footnote_clobber_prefix: Option,
/// Whether to support GFM strikethrough (if enabled in `constructs`) with
/// a single tilde (default: `true`).
///
/// Single tildes work on github.com but are technically prohibited by GFM.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark, micromark_with_options, Options, Constructs};
/// # fn main() -> Result<(), String> {
///
/// // micromark supports single tildes by default:
/// assert_eq!(
/// micromark_with_options(
/// "~a~",
/// &Options {
/// constructs: Constructs::gfm(),
/// ..Options::default()
/// }
/// )?,
/// "a
"
/// );
///
/// // Pass `gfm_strikethrough_single_tilde: false` to turn that off:
/// assert_eq!(
/// micromark_with_options(
/// "~a~",
/// &Options {
/// constructs: Constructs::gfm(),
/// gfm_strikethrough_single_tilde: false,
/// ..Options::default()
/// }
/// )?,
/// "~a~
"
/// );
/// # Ok(())
/// # }
/// ```
pub gfm_strikethrough_single_tilde: bool,
/// Whether to support the GFM tagfilter, when `allow_dangerous_html` is on
/// (default: `false`).
///
/// The tagfilter is kinda weird and kinda useless.
/// The tag filter is a naïve attempt at XSS protection.
/// You should use a proper HTML sanitizing algorithm.
///
/// ## Examples
///
/// ```
/// use micromark::{micromark_with_options, Options, Constructs};
/// # fn main() -> Result<(), String> {
///
/// // With `allow_dangerous_html`, micromark passes HTML through untouched:
/// assert_eq!(
/// micromark_with_options(
/// "