use crate::util::{
line_ending::LineEnding,
mdx::{EsmParse as MdxEsmParse, ExpressionParse as MdxExpressionParse},
};
use alloc::{boxed::Box, fmt, string::String};
#[allow(clippy::struct_excessive_bools)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(rename_all = "camelCase")
)]
pub struct Constructs {
pub attention: bool,
pub autolink: bool,
pub block_quote: bool,
pub character_escape: bool,
pub character_reference: bool,
pub code_indented: bool,
pub code_fenced: bool,
pub code_text: bool,
pub definition: bool,
pub frontmatter: bool,
pub gfm_autolink_literal: bool,
pub gfm_footnote_definition: bool,
pub gfm_label_start_footnote: bool,
pub gfm_strikethrough: bool,
pub gfm_table: bool,
pub gfm_task_list_item: bool,
pub hard_break_escape: bool,
pub hard_break_trailing: bool,
pub heading_atx: bool,
pub heading_setext: bool,
pub html_flow: bool,
pub html_text: bool,
pub label_start_image: bool,
pub label_start_link: bool,
pub label_end: bool,
pub list_item: bool,
pub math_flow: bool,
pub math_text: bool,
pub mdx_esm: bool,
pub mdx_expression_flow: bool,
pub mdx_expression_text: bool,
pub mdx_jsx_flow: bool,
pub mdx_jsx_text: bool,
pub thematic_break: bool,
}
impl Default for Constructs {
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 {
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()
}
}
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()
}
}
}
#[allow(clippy::struct_excessive_bools)]
#[derive(Clone, Debug, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(default, rename_all = "camelCase")
)]
pub struct CompileOptions {
pub allow_any_img_src: bool,
pub allow_dangerous_html: bool,
pub allow_dangerous_protocol: bool,
#[allow(clippy::doc_markdown)]
pub default_line_ending: LineEnding,
pub gfm_footnote_back_label: Option<String>,
pub gfm_footnote_clobber_prefix: Option<String>,
pub gfm_footnote_label_attributes: Option<String>,
pub gfm_footnote_label_tag_name: Option<String>,
pub gfm_footnote_label: Option<String>,
pub gfm_task_list_item_checkable: bool,
pub gfm_tagfilter: bool,
pub heading_ids: bool,
}
impl CompileOptions {
pub fn gfm() -> Self {
Self {
gfm_tagfilter: true,
..Self::default()
}
}
}
#[allow(clippy::struct_excessive_bools)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(default, rename_all = "camelCase")
)]
pub struct ParseOptions {
#[cfg_attr(feature = "serde", serde(default))]
pub constructs: Constructs,
#[cfg_attr(feature = "serde", serde(default))]
pub inline_code_info: bool,
#[cfg_attr(feature = "serde", serde(default))]
pub html_block_blank_lines: bool,
#[cfg_attr(feature = "serde", serde(default))]
pub html_tag_namespaces: bool,
#[cfg_attr(feature = "serde", serde(default))]
pub gfm_strikethrough_single_tilde: bool,
#[cfg_attr(feature = "serde", serde(default))]
pub math_text_single_dollar: bool,
#[cfg_attr(feature = "serde", serde(skip))]
pub mdx_expression_parse: Option<Box<MdxExpressionParse>>,
#[cfg_attr(feature = "serde", serde(skip))]
pub mdx_esm_parse: Option<Box<MdxEsmParse>>,
}
impl fmt::Debug for ParseOptions {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ParseOptions")
.field("constructs", &self.constructs)
.field("inline_code_info", &self.inline_code_info)
.field("html_block_blank_lines", &self.html_block_blank_lines)
.field("html_tag_namespaces", &self.html_tag_namespaces)
.field(
"gfm_strikethrough_single_tilde",
&self.gfm_strikethrough_single_tilde,
)
.field("math_text_single_dollar", &self.math_text_single_dollar)
.field(
"mdx_expression_parse",
&self.mdx_expression_parse.as_ref().map(|_d| "[Function]"),
)
.field(
"mdx_esm_parse",
&self.mdx_esm_parse.as_ref().map(|_d| "[Function]"),
)
.finish()
}
}
impl Default for ParseOptions {
fn default() -> Self {
Self {
constructs: Constructs::default(),
inline_code_info: false,
html_block_blank_lines: false,
html_tag_namespaces: false,
gfm_strikethrough_single_tilde: true,
math_text_single_dollar: true,
mdx_expression_parse: None,
mdx_esm_parse: None,
}
}
}
impl ParseOptions {
pub fn gfm() -> Self {
Self {
constructs: Constructs::gfm(),
..Self::default()
}
}
pub fn mdx() -> Self {
Self {
constructs: Constructs::mdx(),
..Self::default()
}
}
}
#[allow(clippy::struct_excessive_bools)]
#[derive(Debug, Default)]
#[cfg_attr(
feature = "serde",
derive(serde::Serialize, serde::Deserialize),
serde(default)
)]
pub struct Options {
pub parse: ParseOptions,
pub compile: CompileOptions,
}
impl Options {
pub fn gfm() -> Self {
Self {
parse: ParseOptions::gfm(),
compile: CompileOptions::gfm(),
}
}
}
#[cfg(test)]
#[path = "configuration/tests.rs"]
mod tests;