如何在Golang中通过添加section标签将markdown转换为HTML

Gia*_* Le 3 html markdown go

我有下面的降价

## Hello
### This is a test message
Ligisnfmkdfn
Run Code Online (Sandbox Code Playgroud)

我使用 GO 模块gomarkdown通过 CommonExtensions 和 AutoHeadingIDs 解析器将 markdown 转换为 HTML,我得到的结果是

<h2 id="helo">Hello</h2>
<h3 id="this-is-a-test-message">This is a test message</h3>
<p>Ligisnfmkdfn</p>
Run Code Online (Sandbox Code Playgroud)

我怎样才能得到像在nodejs中使用markdown-it-header-sections一样的结果

<section id="helo">
   <h2>Hello</h2>
   <section id="this-is-a-test-message">
      <h3>This is a test message</h3>
      <p>Ligisnfmkdfn</p>
   </section>
</section>
Run Code Online (Sandbox Code Playgroud)

Zac*_*ung 5

这是一个相当完整的解决方案:

\n
package main\n\nimport (\n    "fmt"\n    "io"\n    "regexp"\n    "strings"\n\n    "github.com/gomarkdown/markdown"\n    "github.com/gomarkdown/markdown/ast"\n    "github.com/gomarkdown/markdown/html"\n)\n\n// levels tracks how deep we are in a heading "structure"\nvar levels []int\n\nfunc hasLevels() bool {\n    return len(levels) > 0\n}\n\nfunc lastLevel() int {\n    if hasLevels() {\n        return levels[len(levels)-1]\n    }\n    return 0\n}\n\nfunc popLevel() int {\n    level := lastLevel()\n    levels = levels[:len(levels)-1]\n    return level\n}\n\nfunc pushLevel(x int) {\n    levels = append(levels, x)\n}\n\nvar reID = regexp.MustCompile(`\\s+`)\n\n// renderSections catches an ast.Heading node, and wraps the node\n// and its "children" nodes in <section>...</section> tags; there\'s no\n// real hierarchy in Markdown, so we make one up by saying things like:\n// - H2 is a child of H1, and so forth from 1 \xe2\x86\x92 2 \xe2\x86\x92 3 ... \xe2\x86\x92 N\n// - an H1 is a sibling of another H1\nfunc renderSections(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {\n    openSection := func(level int, id string) {\n        w.Write([]byte(fmt.Sprintf("<section id=\\"%s\\">\\n", id)))\n        pushLevel(level)\n    }\n    closeSection := func() {\n        w.Write([]byte("</section>\\n"))\n        popLevel()\n    }\n\n    if _, ok := node.(*ast.Heading); ok {\n        level := node.(*ast.Heading).Level\n        if entering {\n            // close heading-sections deeper than this level; we\'ve "come up" some number of levels\n            for lastLevel() > level {\n                closeSection()\n            }\n\n            txtNode := node.GetChildren()[0]\n            if _, ok := txtNode.(*ast.Text); !ok {\n                panic(fmt.Errorf("expected txtNode to be *ast.Text; got %T", txtNode))\n            }\n            headTxt := string(txtNode.AsLeaf().Literal)\n            id := strings.ToLower(reID.ReplaceAllString(headTxt, "-"))\n\n            openSection(level, id)\n        }\n    }\n\n    // at end of document\n    if _, ok := node.(*ast.Document); ok {\n        if !entering {\n            for hasLevels() {\n                closeSection()\n            }\n        }\n    }\n\n    // continue as normal\n    return ast.GoToNext, false\n}\n\nfunc main() {\n    lines := []string{\n        "## Hello",\n        "### This is a test message",\n        "Ligisnfmkdfn",\n    }\n    md := strings.Join(lines, "\\n")\n\n    opts := html.RendererOptions{\n        Flags:          html.CommonFlags,\n        RenderNodeHook: renderSections,\n    }\n    renderer := html.NewRenderer(opts)\n\n    html := markdown.ToHTML([]byte(md), nil, renderer)\n\n    fmt.Println(string(html))\n}\n
Run Code Online (Sandbox Code Playgroud)\n

当我运行它时,我得到:

\n
<section id="hello">\n  <h2>Hello</h2>\n  <section id="this-is-a-test-message">\n    <h3>This is a test message</h3>\n    <p>Ligisnfmkdfn</p>\n  </section>\n</section>\n
Run Code Online (Sandbox Code Playgroud)\n

我说它还算完整,因为它足够聪明,可以处理如下输入:

\n
lines := []string{\n    "# H1\xce\xb1",\n    "## H2A",\n    "## H2B",\n    "## H2C",\n    "### H31",\n    "#### H4I",\n    "## H2D",\n    "# H1\xce\xb2",\n    "## H2E",\n}\n
Run Code Online (Sandbox Code Playgroud)\n

它产生:

\n
<section id="h1\xce\xb1">\n  <h1>H1\xce\xb1</h1>\n  <section id="h2a">\n    <h2>H2A</h2>\n  </section>\n  <section id="h2b">\n    <h2>H2B</h2>\n  </section>\n  <section id="h2c">\n    <h2>H2C</h2>\n    <section id="h31">\n      <h3>H31</h3>\n      <section id="h4i">\n        <h4>H4I</h4>\n      </section>\n    </section>\n  </section>\n  <section id="h2d">\n    <h2>H2D</h2>\n  </section>\n</section>\n<section id="h1\xce\xb2">\n  <h1>H1\xce\xb2</h1>\n  <section id="h2e">\n    <h2>H2E</h2>\n  </section>\n</section>\n
Run Code Online (Sandbox Code Playgroud)\n

但我还没有对此进行严格测试,所以我不确定它可能在哪里不符合预期。

\n