gomarkdown / markdown

markdown parser and HTML renderer for Go
Other
1.36k stars 171 forks source link

Unexpected behaviour with Container.Content #294

Closed simonasGit closed 10 months ago

simonasGit commented 10 months ago

The markdown:

- dir1
    - [title](http://url)
- dir2
    - subsecond
    - something
- [hello](urlie)
  #tag1 #tag2

some text

'bout sumthin' f

  > yes
  > this is a
  > sandwich
- [hello](url)
  #tag1 #tag2
- [hello](url)
  #tag1 #tag2
package main

import (
    "fmt"
    "os"

    "github.com/gomarkdown/markdown/ast"
    "github.com/gomarkdown/markdown/parser"
)

var data, _ = os.ReadFile("text")

func main() {
    var p = parser.New()
    doc := p.Parse([]byte(data))
    ast.WalkFunc(doc, func(node ast.Node, entering bool) ast.WalkStatus {
        switch node.(type) {
        case *ast.Paragraph:
            fmt.Printf("%#v", node.AsContainer().Content)
        }
        return ast.GoToNext
    })
}

This looks pretty much akin to parser.Parse():

<...>
ast.WalkFunc(p.Doc, func(node ast.Node, entering bool) ast.WalkStatus {
        switch node.(type) {
        case *ast.Paragraph, *ast.Heading, *ast.TableCell:
            p.Inline(node, node.AsContainer().Content)
            node.AsContainer().Content = nil
        }
        return ast.GoToNext
    })
<...>

However the output is

[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]b
yte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)[]byte(nil)

What's going on with Content being empty?

kjk commented 10 months ago

The answer is in the snippet you pointed out:

            node.AsContainer().Content = nil

Content is used to temporarily hold the text but it's then parsed by p.Inline and then cleared.

maybe this will work:

func contentToString(d1 []byte, d2 []byte) string {
    if d1 != nil {
        return string(d1)
    }
    if d2 != nil {
        return string(d2)
    }
    return ""
}

func getContent(node Node) string {
    if c := node.AsContainer(); c != nil {
        return contentToString(c.Literal, c.Content)
    }
    leaf := node.AsLeaf()
    return contentToString(leaf.Literal, leaf.Content)
}