实现功能
- 增加文章详情页Toc文章目录
实现思路
对文章内容提取 h1, h2, h3, h4, h5 标签与锚,这里我们将采用到第三方包
- github.com/PuerkitoBio/goquery
// handler/post.go
html = `
<h1 id="H55oy1">语雀文章内容</h1>
<h2 id="H55oy2">语雀文章内容</h2>
<h3 id="H55oy3">语雀文章内容</h3>
<h4 id="H55oy4">语雀文章内容</h4>
<h5 id="H55oy5">语雀文章内容</h5>
`
doc, _ := goquery.NewDocumentFromReader(strings.NewReader(html))
var navs []*Nav
doc.Find("h1, h2, h3, h4, h5").Each(func(i int, s *goquery.Selection) {
// ...
navs = append(navs, &Nav{
ID: "",
Title: "",
Level: "",
})
})
type Nav struct {
ID string
Title string
Level int
}
详细实现
- handler/post.go#PostDetail, 增加 toc 变量
theme/default/detail.html, 渲染 toc
// PostDetail 文章详情页 func PostDetail(s service.IYuQue) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // 文章内容 content := detail.Data.BodyHtml // 替换html中的cdn链接进行反向代理 content = strings.Replace(content, "https://cdn.nlark.com/", "/", -1) var navs []*Nav doc, _ := goquery.NewDocumentFromReader(strings.NewReader(content)) doc.Find("h1, h2, h3, h4, h5").Each(func(i int, s *goquery.Selection) { // 提取 ID id, _ := s.Attr("id") id = strings.ReplaceAll(id, "\\", "") id = strings.ReplaceAll(id, "\"", "") // 提取标题 text := s.Text() // 提取标题等级 level := 1 if s.Is("h1") { level = 1 } if s.Is("h2") { level = 2 } if s.Is("h3") { level = 3 } if s.Is("h4") { level = 4 } if s.Is("h5") { level = 5 } nav := &Nav{ Text: text, Level: level, ID: id, } navs = append(navs, nav) }) // 模块变量 post := Post{ Title: detail.Data.Title, Content: template.HTML(content), CreatedAt: detail.Data.CreatedAt, Toc: navs, } t.Execute(w, map[string]interface{}{ "post": post, }) } }
{{ if .post.Toc }}
<div class="widget widget-content">
<h3 class="widget-title">文章目录</h3>
<ul style="list-style-type: none;padding-left: 0;">
{{ range $i, $v := .post.Toc }}
{{ if eq $v.Level 1}}
<li>
<a href="#{{ $v.ID }}" >{{ $v.Text }}</a>
</li>
{{ end }}
{{ if eq $v.Level 2}}
<li>
<a href="#{{ $v.ID }}" style="padding-left: 15px;" >{{ $v.Text }}</a>
</li>
{{ end }}
{{ if eq $v.Level 3}}
<li>
<a href="#{{ $v.ID }}" style="padding-left: 30px;" >{{ $v.Text }}</a>
</li>
{{ end }}
{{ if eq $v.Level 4}}
<li>
<a href="#{{ $v.ID }}" style="padding-left: 45px;" >{{ $v.Text }}</a>
</li>
{{ end }}
{{ if eq $v.Level 5}}
<li>
<a href="#{{ $v.ID }}" style="padding-left: 60px;" >{{ $v.Text }}</a>
</li>
{{ end }}
{{ end }}
</ul>
</div>
{{ end }}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。