简体   繁体   English

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

[英]How to convert markdown to HTML in Golang with adding section tag

I have the markdown below我有下面的 markdown

## Hello
### This is a test message
Ligisnfmkdfn

And I use the GO module gomarkdown to convert markdown to HTML with CommonExtensions and AutoHeadingIDs parser and I got the result are我使用 GO 模块gomarkdown将 markdown 转换为 HTML 与 CommonExtensions 和 AutoHeadingIDs 解析器,我得到的结果是

<h2 id="helo">Hello</h2>
<h3 id="this-is-a-test-message">This is a test message</h3>
<p>Ligisnfmkdfn</p>

How can I get the result like using markdown-it-header-sections in nodejs我怎样才能得到像在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>

Here's a moderately complete solution:这是一个适度完整的解决方案:

package main

import (
    "fmt"
    "io"
    "regexp"
    "strings"

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

// levels tracks how deep we are in a heading "structure"
var levels []int

func hasLevels() bool {
    return len(levels) > 0
}

func lastLevel() int {
    if hasLevels() {
        return levels[len(levels)-1]
    }
    return 0
}

func popLevel() int {
    level := lastLevel()
    levels = levels[:len(levels)-1]
    return level
}

func pushLevel(x int) {
    levels = append(levels, x)
}

var reID = regexp.MustCompile(`\s+`)

// renderSections catches an ast.Heading node, and wraps the node
// and its "children" nodes in <section>...</section> tags; there's no
// real hierarchy in Markdown, so we make one up by saying things like:
// - H2 is a child of H1, and so forth from 1 → 2 → 3 ... → N
// - an H1 is a sibling of another H1
func renderSections(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
    openSection := func(level int, id string) {
        w.Write([]byte(fmt.Sprintf("<section id=\"%s\">\n", id)))
        pushLevel(level)
    }
    closeSection := func() {
        w.Write([]byte("</section>\n"))
        popLevel()
    }

    if _, ok := node.(*ast.Heading); ok {
        level := node.(*ast.Heading).Level
        if entering {
            // close heading-sections deeper than this level; we've "come up" some number of levels
            for lastLevel() > level {
                closeSection()
            }

            txtNode := node.GetChildren()[0]
            if _, ok := txtNode.(*ast.Text); !ok {
                panic(fmt.Errorf("expected txtNode to be *ast.Text; got %T", txtNode))
            }
            headTxt := string(txtNode.AsLeaf().Literal)
            id := strings.ToLower(reID.ReplaceAllString(headTxt, "-"))

            openSection(level, id)
        }
    }

    // at end of document
    if _, ok := node.(*ast.Document); ok {
        if !entering {
            for hasLevels() {
                closeSection()
            }
        }
    }

    // continue as normal
    return ast.GoToNext, false
}

func main() {
    lines := []string{
        "## Hello",
        "### This is a test message",
        "Ligisnfmkdfn",
    }
    md := strings.Join(lines, "\n")

    opts := html.RendererOptions{
        Flags:          html.CommonFlags,
        RenderNodeHook: renderSections,
    }
    renderer := html.NewRenderer(opts)

    html := markdown.ToHTML([]byte(md), nil, renderer)

    fmt.Println(string(html))
}

When I run that, I get:当我运行它时,我得到:

<section id="hello">
  <h2>Hello</h2>
  <section id="this-is-a-test-message">
    <h3>This is a test message</h3>
    <p>Ligisnfmkdfn</p>
  </section>
</section>

I say it's moderately complete because it's smart enough to deal with input like this:我说它是适度完整的,因为它足够聪明,可以处理这样的输入:

lines := []string{
    "# H1α",
    "## H2A",
    "## H2B",
    "## H2C",
    "### H31",
    "#### H4I",
    "## H2D",
    "# H1β",
    "## H2E",
}

and it produces:它产生:

<section id="h1α">
  <h1>H1α</h1>
  <section id="h2a">
    <h2>H2A</h2>
  </section>
  <section id="h2b">
    <h2>H2B</h2>
  </section>
  <section id="h2c">
    <h2>H2C</h2>
    <section id="h31">
      <h3>H31</h3>
      <section id="h4i">
        <h4>H4I</h4>
      </section>
    </section>
  </section>
  <section id="h2d">
    <h2>H2D</h2>
  </section>
</section>
<section id="h1β">
  <h1>H1β</h1>
  <section id="h2e">
    <h2>H2E</h2>
  </section>
</section>

But I haven't rigorously tested this, so I'm not sure where it might not meet expectations.但是我没有对此进行严格的测试,所以我不确定它在哪里可能不符合预期。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM