kivikakk / comrak

CommonMark + GFM compatible Markdown parser and renderer
Other
1.19k stars 139 forks source link

Inconsistent `sourcepos` for two link types #478

Open SamWilsn opened 2 days ago

SamWilsn commented 2 days ago

Running into a bit of a confusing problem (at least for me.) Two different kinds of links give different sourcepos values when I believe they should be the same.

Here's some demo code:

use comrak::{
    arena_tree::{Node, NodeEdge},
    nodes::{NodeValue, Sourcepos},
    parse_document, Arena, ExtensionOptions, Options,
};

fn demo(source: &str) -> Sourcepos {
    let arena = Arena::new();
    let mut extension = ExtensionOptions::default();
    extension.autolink = true;

    let root = parse_document(
        &arena,
        source,
        &Options {
            extension,
            ..Default::default()
        },
    );

    let link = root
        .traverse()
        .filter_map(|x| match x {
            NodeEdge::Start(Node { data, .. }) => Some(data.borrow().clone()),
            _ => None,
        })
        .filter(|x| matches!(x.value, NodeValue::Link(_)))
        .next()
        .unwrap();

    link.sourcepos
}

fn main() {
    let a = demo("hello <https://example.com/fooo> world");
    let b = demo("hello [foo](https://example.com) world");
    assert_eq!(a, b);
}

And the output I'm getting:

thread 'main' panicked at src/main.rs:37:5:
assertion `left == right` failed
  left: Sourcepos { start: LineColumn { line: 1, column: 8 }, end: LineColumn { line: 1, column: 33 } }
 right: Sourcepos { start: LineColumn { line: 1, column: 7 }, end: LineColumn { line: 1, column: 32 } }
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
digitalmoksha commented 1 day ago

Hmm, I think you're right. It looks like [foo](https://example.com) is generating the correct sourcepos, but <https://example.com/fooo> isn't. They should give the same value, as both links start and end in the same column.

SamWilsn commented 1 day ago

There seems to be a similar issue with footnote-style links:

    let b = demo("hello [foo][ooooooooooooooooooo] world\n\n[ooooooooooooooooooo]: https://example.com");