From cd5bb2d16c6b28332b0b6077b27b2b90a8051896 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Thu, 6 Oct 2022 15:57:55 +0200 Subject: Refactor to split parse from compile options --- src/lib.rs | 435 ++++++++++++++++++++++++++++++++++----------------------- src/parser.rs | 9 +- src/to_html.rs | 8 +- 3 files changed, 273 insertions(+), 179 deletions(-) (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 8eaa2bb..02fb5f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -168,7 +168,7 @@ pub type MdxEsmParse = dyn Fn(&str) -> MdxSignal; /// Not all constructs can be configured. /// Notably, blank lines and paragraphs cannot be turned off. #[allow(clippy::struct_excessive_bools)] -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct Constructs { /// Attention. /// @@ -392,9 +392,9 @@ pub struct Constructs { /// ^^^^^^^^^^^^^^^^^ /// ``` /// - /// > 👉 **Note**: you *must* pass [`options.mdx_esm_parse`][MdxEsmParse] - /// > too. - /// > Otherwise, this option has no affect. + /// > 👉 **Note**: you *must* pass [`mdx_esm_parse`][MdxEsmParse] + /// > in [`ParseOptions`][] too. + /// > Otherwise, this option has no effect. pub mdx_esm: bool, /// MDX: expression (flow). /// @@ -522,10 +522,10 @@ impl Constructs { /// (autolinks, code (indented), html), and turns on MDX (JSX, /// expressions, ESM). /// - /// > 👉 **Note**: you *must* pass [`options.mdx_esm_parse`][MdxEsmParse] - /// > to support ESM. + /// > 👉 **Note**: you *must* pass [`mdx_esm_parse`][MdxEsmParse] + /// > in [`ParseOptions`][] too to support ESM. /// > You *can* pass - /// > [`options.mdx_expression_parse`][MdxExpressionParse] + /// > [`mdx_expression_parse`][MdxExpressionParse] /// > to parse expressions according to a certain grammar (typically, a /// > programming language). #[must_use] @@ -545,10 +545,10 @@ impl Constructs { } } -/// Configuration (optional). +/// Configuration that describes how to compile to HTML. #[allow(clippy::struct_excessive_bools)] -pub struct Options { - // Note: when adding fields, don’t forget to add them to `fmt::Debug` below. +#[derive(Clone, Debug, Default)] +pub struct CompileOptions { /// Whether to allow (dangerous) HTML. /// The default is `false`, you can turn it on to `true` for trusted /// content. @@ -556,7 +556,7 @@ pub struct Options { /// ## Examples /// /// ``` - /// use micromark::{micromark, micromark_with_options, Options}; + /// use micromark::{micromark, micromark_with_options, CompileOptions, Options}; /// # fn main() -> Result<(), String> { /// /// // micromark is safe by default: @@ -570,7 +570,10 @@ pub struct Options { /// micromark_with_options( /// "Hi, venus!", /// &Options { - /// allow_dangerous_html: true, + /// compile: CompileOptions { + /// allow_dangerous_html: true, + /// ..CompileOptions::default() + /// }, /// ..Options::default() /// } /// )?, @@ -588,7 +591,7 @@ pub struct Options { /// ## Examples /// /// ``` - /// use micromark::{micromark, micromark_with_options, Options}; + /// use micromark::{micromark, micromark_with_options, CompileOptions, Options}; /// # fn main() -> Result<(), String> { /// /// // micromark is safe by default: @@ -602,7 +605,10 @@ pub struct Options { /// micromark_with_options( /// "", /// &Options { - /// allow_dangerous_protocol: true, + /// compile: CompileOptions { + /// allow_dangerous_protocol: true, + /// ..CompileOptions::default() + /// }, /// ..Options::default() /// } /// )?, @@ -613,41 +619,8 @@ pub struct Options { /// ``` 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`. + /// Default line ending to use when compiling to HTML, for line endings not + /// in `value`. /// /// Generally, micromark copies line endings (`\r`, `\n`, `\r\n`) in the /// markdown document over to the compiled HTML. @@ -662,7 +635,7 @@ pub struct Options { /// ## Examples /// /// ``` - /// use micromark::{micromark, micromark_with_options, Options, LineEnding}; + /// use micromark::{micromark, micromark_with_options, CompileOptions, LineEnding, Options}; /// # fn main() -> Result<(), String> { /// /// // micromark uses `\n` by default: @@ -676,7 +649,10 @@ pub struct Options { /// micromark_with_options( /// "> a", /// &Options { - /// default_line_ending: LineEnding::CarriageReturnLineFeed, + /// compile: CompileOptions { + /// default_line_ending: LineEnding::CarriageReturnLineFeed, + /// ..CompileOptions::default() + /// }, /// ..Options::default() /// } /// )?, @@ -696,17 +672,14 @@ pub struct Options { /// ## Examples /// /// ``` - /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// use micromark::{micromark, micromark_with_options, CompileOptions, Options, ParseOptions}; /// # 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() - /// } + /// &Options::gfm() /// )?, /// "

1

\n

Footnotes

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" /// ); @@ -716,9 +689,11 @@ pub struct Options { /// 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() + /// parse: ParseOptions::gfm(), + /// compile: CompileOptions { + /// gfm_footnote_label: Some("Notes de bas de page".to_string()), + /// ..CompileOptions::gfm() + /// } /// } /// )?, /// "

1

\n

Notes de bas de page

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" @@ -735,17 +710,14 @@ pub struct Options { /// ## Examples /// /// ``` - /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// use micromark::{micromark, micromark_with_options, CompileOptions, Options, ParseOptions}; /// # 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() - /// } + /// &Options::gfm() /// )?, /// "

1

\n

Footnotes

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" /// ); @@ -755,9 +727,11 @@ pub struct Options { /// micromark_with_options( /// "[^a]\n\n[^a]: b", /// &Options { - /// constructs: Constructs::gfm(), - /// gfm_footnote_label_tag_name: Some("h1".to_string()), - /// ..Options::default() + /// parse: ParseOptions::gfm(), + /// compile: CompileOptions { + /// gfm_footnote_label_tag_name: Some("h1".to_string()), + /// ..CompileOptions::gfm() + /// } /// } /// )?, /// "

1

\n

Footnotes

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" @@ -780,17 +754,14 @@ pub struct Options { /// ## Examples /// /// ``` - /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// use micromark::{micromark, micromark_with_options, CompileOptions, Options, ParseOptions}; /// # 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() - /// } + /// &Options::gfm() /// )?, /// "

1

\n

Footnotes

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" /// ); @@ -800,9 +771,11 @@ pub struct Options { /// micromark_with_options( /// "[^a]\n\n[^a]: b", /// &Options { - /// constructs: Constructs::gfm(), - /// gfm_footnote_label_attributes: Some("class=\"footnote-heading\"".to_string()), - /// ..Options::default() + /// parse: ParseOptions::gfm(), + /// compile: CompileOptions { + /// gfm_footnote_label_attributes: Some("class=\"footnote-heading\"".to_string()), + /// ..CompileOptions::gfm() + /// } /// } /// )?, /// "

1

\n

Footnotes

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" @@ -820,17 +793,14 @@ pub struct Options { /// ## Examples /// /// ``` - /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// use micromark::{micromark, micromark_with_options, CompileOptions, Options, ParseOptions}; /// # 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() - /// } + /// &Options::gfm() /// )?, /// "

1

\n

Footnotes

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" /// ); @@ -840,9 +810,11 @@ pub struct Options { /// micromark_with_options( /// "[^a]\n\n[^a]: b", /// &Options { - /// constructs: Constructs::gfm(), - /// gfm_footnote_back_label: Some("Arrière".to_string()), - /// ..Options::default() + /// parse: ParseOptions::gfm(), + /// compile: CompileOptions { + /// gfm_footnote_back_label: Some("Arrière".to_string()), + /// ..CompileOptions::gfm() + /// } /// } /// )?, /// "

1

\n

Footnotes

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" @@ -870,17 +842,14 @@ pub struct Options { /// ## Examples /// /// ``` - /// use micromark::{micromark, micromark_with_options, Options, Constructs}; + /// use micromark::{micromark, micromark_with_options, CompileOptions, Options, ParseOptions}; /// # 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() - /// } + /// &Options::gfm() /// )?, /// "

1

\n

Footnotes

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" /// ); @@ -890,9 +859,11 @@ pub struct Options { /// micromark_with_options( /// "[^a]\n\n[^a]: b", /// &Options { - /// constructs: Constructs::gfm(), - /// gfm_footnote_clobber_prefix: Some("".to_string()), - /// ..Options::default() + /// parse: ParseOptions::gfm(), + /// compile: CompileOptions { + /// gfm_footnote_clobber_prefix: Some("".to_string()), + /// ..CompileOptions::gfm() + /// } /// } /// )?, /// "

1

\n

Footnotes

\n
    \n
  1. \n

    b ↩

    \n
  2. \n
\n
\n" @@ -902,94 +873,161 @@ pub struct Options { /// ``` pub gfm_footnote_clobber_prefix: Option, - /// Whether to support GFM strikethrough (if enabled in `constructs`) with - /// a single tilde (default: `true`). + /// Whether to support the GFM tagfilter, when `allow_dangerous_html` is on + /// (default: `false`). /// - /// Single tildes work on github.com but are technically prohibited by GFM. + /// 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, micromark_with_options, Options, Constructs}; + /// use micromark::{micromark_with_options, CompileOptions, Options, ParseOptions}; /// # fn main() -> Result<(), String> { /// - /// // micromark supports single tildes by default: + /// // With `allow_dangerous_html`, micromark passes HTML through untouched: /// assert_eq!( /// micromark_with_options( - /// "~a~", + /// "