yuin / goldmark

:trophy: A markdown parser written in Go. Easy to extend, standard(CommonMark) compliant, well structured.
MIT License
3.68k stars 255 forks source link

Link.Lines() and Image.Lines() panic #286

Closed ffel closed 2 years ago

ffel commented 2 years ago

Both ast.Link and ast.Image panic when calling their Lines() method.

See example code below where visitNodes tries to call Lines() in case the node is an Image.

var source string = `### Hello goldmark custom renderer

![Caption](fig.png)
`

func Example_AstPrinter() {
    ap := &AstPrinter{[]byte(source)}
    md := goldmark.New(
        goldmark.WithRenderer(ap),
    )
    var buf bytes.Buffer
    if err := md.Convert(ap.contents, &buf); err != nil {
        fmt.Printf("err: %v\n", err)
    }

    // output:
    // nothing is printed as the code panics
}

type AstPrinter struct {
    contents []byte
}

func (v *AstPrinter) Render(w io.Writer, source []byte, n ast.Node) error {

    v.visitNodes(n, "")

    return nil
}

func (v *AstPrinter) visitNodes(n ast.Node, prefix string) {
    switch node := n.(type) {
    case *ast.Image:
        // panic:
        fmt.Printf("-- Image %#v\n", node.Lines())
    default:
        fmt.Printf("%v%v\n", prefix, node.Kind().String())
    }

    if n.HasChildren() {
        last := n.LastChild()

        for n = n.FirstChild(); ; n = n.NextSibling() {

            v.visitNodes(n, prefix+"  ")

            if n == last {
                return
            }
        }
    }
}

func (v *AstPrinter) AddOptions(...renderer.Option) {
}

I suspect the following reason causes the panic:

Both ast.Link and ast.Image embed (a private struct) baseLink, ast.Link.Lines() and ast.Image.Lines() delegate method Lines() to the embedded and private baseLink due to which the application crashes.

The application panics in 1.4.4. I suspect it will panic in 1.4.9 as well as baseLink is still a private embedded struct.

yuin commented 2 years ago

This works as expected. Inline nodes like Image, Link etc... can not call Lines()

image