Skip to content

Indented footnote definitions confuse the parser #623

@allenap

Description

@allenap

The following:

Foo[^foo]
Bar[^bar]

[^foo]:
    FooDef1
    FooDef2

[^bar]:
    BarDef

renders like so on GitHub:

image

but pulldown_cmark::Parser gets confused:

  1. It sees the definition text as indented code blocks.
  2. It does not see the end of the first definition before the start of the second.

Running the following code:

static MARKDOWN: &str = r#"\
Foo[^foo]
Bar[^bar]

[^foo]:
    FooDef1
    FooDef2

[^bar]:
    BarDef
"#;

fn main() {
    use pulldown_cmark::{Options, Parser};
    let options = Options::empty().union(Options::ENABLE_FOOTNOTES);
    let parser = Parser::new_ext(MARKDOWN, options);
    for event in parser {
        eprintln!("{event:?}");
    }
}

yields the following events:

  • Start(Paragraph)
  • HardBreak
  • Text(Borrowed("Foo"))
  • FootnoteReference(Borrowed("foo"))
  • SoftBreak
  • Text(Borrowed("Bar"))
  • FootnoteReference(Borrowed("bar"))
  • End(Paragraph)
  • Start(FootnoteDefinition(Borrowed("foo")))
  • Start(CodeBlock(Indented))
  • Text(Borrowed("FooDef1\n"))
  • Text(Borrowed("FooDef2\n"))
  • End(CodeBlock(Indented))
  • Start(FootnoteDefinition(Borrowed("bar")))
  • Start(CodeBlock(Indented))
  • Text(Borrowed("BarDef\n"))
  • End(CodeBlock(Indented))
  • End(FootnoteDefinition(Borrowed("bar")))
  • End(FootnoteDefinition(Borrowed("foo")))

I would expect it to:

  • treat the indented definitions as part of the definition, and
  • end the first definition before starting the second.

There is a workaround:

Foo[^foo]
Bar[^bar]

[^foo]: FooDef1
    FooDef2

[^bar]: BarDef

This yields:

  • ...
  • Start(FootnoteDefinition(Borrowed("foo")))
  • Start(Paragraph)
  • Text(Borrowed("FooDef1"))
  • SoftBreak
  • Text(Borrowed("FooDef2"))
  • End(Paragraph)
  • End(FootnoteDefinition(Borrowed("foo")))
  • Start(FootnoteDefinition(Borrowed("bar")))
  • Start(Paragraph)
  • Text(Borrowed("BarDef"))
  • End(Paragraph)
  • End(FootnoteDefinition(Borrowed("bar")))

i.e. by putting content on the same line as the definition begins, the parser is happy. Unfortunately, at least one code formatter in VSCode for Markdown (maybe the built-in one?) likes to format long definitions indented below the [^foo]: opener.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions