[英]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.