diff --git a/modules/markup/markdown/goldmark.go b/modules/markup/markdown/goldmark.go
index 9b6cd3aaefb..1750128dec8 100644
--- a/modules/markup/markdown/goldmark.go
+++ b/modules/markup/markdown/goldmark.go
@@ -27,13 +27,6 @@ import (
var byteMailto = []byte("mailto:")
-// Header holds the data about a header.
-type Header struct {
- Level int
- Text string
- ID string
-}
-
// ASTTransformer is a default transformer of the goldmark tree.
type ASTTransformer struct{}
@@ -42,12 +35,13 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
metaData := meta.GetItems(pc)
firstChild := node.FirstChild()
createTOC := false
- toc := []Header{}
+ ctx := pc.Get(renderContextKey).(*markup.RenderContext)
rc := &RenderConfig{
Meta: "table",
Icon: "table",
Lang: "",
}
+
if metaData != nil {
rc.ToRenderConfig(metaData)
@@ -56,7 +50,7 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
node.InsertBefore(node, firstChild, metaNode)
}
createTOC = rc.TOC
- toc = make([]Header, 0, 100)
+ ctx.TableOfContents = make([]markup.Header, 0, 100)
}
_ = ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
@@ -66,23 +60,20 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
switch v := n.(type) {
case *ast.Heading:
- if createTOC {
- text := n.Text(reader.Source())
- header := Header{
- Text: util.BytesToReadOnlyString(text),
- Level: v.Level,
- }
- if id, found := v.AttributeString("id"); found {
- header.ID = util.BytesToReadOnlyString(id.([]byte))
- }
- toc = append(toc, header)
- } else {
- for _, attr := range v.Attributes() {
- if _, ok := attr.Value.([]byte); !ok {
- v.SetAttribute(attr.Name, []byte(fmt.Sprintf("%v", attr.Value)))
- }
+ for _, attr := range v.Attributes() {
+ if _, ok := attr.Value.([]byte); !ok {
+ v.SetAttribute(attr.Name, []byte(fmt.Sprintf("%v", attr.Value)))
}
}
+ text := n.Text(reader.Source())
+ header := markup.Header{
+ Text: util.BytesToReadOnlyString(text),
+ Level: v.Level,
+ }
+ if id, found := v.AttributeString("id"); found {
+ header.ID = util.BytesToReadOnlyString(id.([]byte))
+ }
+ ctx.TableOfContents = append(ctx.TableOfContents, header)
case *ast.Image:
// Images need two things:
//
@@ -199,12 +190,12 @@ func (g *ASTTransformer) Transform(node *ast.Document, reader text.Reader, pc pa
return ast.WalkContinue, nil
})
- if createTOC && len(toc) > 0 {
+ if createTOC && len(ctx.TableOfContents) > 0 {
lang := rc.Lang
if len(lang) == 0 {
lang = setting.Langs[0]
}
- tocNode := createTOCNode(toc, lang)
+ tocNode := createTOCNode(ctx.TableOfContents, lang)
if tocNode != nil {
node.InsertBefore(node, firstChild, tocNode)
}
diff --git a/modules/markup/markdown/markdown.go b/modules/markup/markdown/markdown.go
index 320c2f7f827..7ebdfea6c4a 100644
--- a/modules/markup/markdown/markdown.go
+++ b/modules/markup/markdown/markdown.go
@@ -34,9 +34,10 @@ var (
)
var (
- urlPrefixKey = parser.NewContextKey()
- isWikiKey = parser.NewContextKey()
- renderMetasKey = parser.NewContextKey()
+ urlPrefixKey = parser.NewContextKey()
+ isWikiKey = parser.NewContextKey()
+ renderMetasKey = parser.NewContextKey()
+ renderContextKey = parser.NewContextKey()
)
type limitWriter struct {
@@ -67,6 +68,7 @@ func newParserContext(ctx *markup.RenderContext) parser.Context {
pc.Set(urlPrefixKey, ctx.URLPrefix)
pc.Set(isWikiKey, ctx.IsWiki)
pc.Set(renderMetasKey, ctx.Metas)
+ pc.Set(renderContextKey, ctx)
return pc
}
diff --git a/modules/markup/markdown/toc.go b/modules/markup/markdown/toc.go
index 9d11b771f7f..fec45103e58 100644
--- a/modules/markup/markdown/toc.go
+++ b/modules/markup/markdown/toc.go
@@ -8,12 +8,13 @@ import (
"fmt"
"net/url"
+ "code.gitea.io/gitea/modules/markup"
"code.gitea.io/gitea/modules/translation/i18n"
"github.com/yuin/goldmark/ast"
)
-func createTOCNode(toc []Header, lang string) ast.Node {
+func createTOCNode(toc []markup.Header, lang string) ast.Node {
details := NewDetails()
summary := NewSummary()
diff --git a/modules/markup/renderer.go b/modules/markup/renderer.go
index cf8b9bace70..53ecbfce2bf 100644
--- a/modules/markup/renderer.go
+++ b/modules/markup/renderer.go
@@ -33,18 +33,26 @@ func Init() {
}
}
+// Header holds the data about a header.
+type Header struct {
+ Level int
+ Text string
+ ID string
+}
+
// RenderContext represents a render context
type RenderContext struct {
- Ctx context.Context
- Filename string
- Type string
- IsWiki bool
- URLPrefix string
- Metas map[string]string
- DefaultLink string
- GitRepo *git.Repository
- ShaExistCache map[string]bool
- cancelFn func()
+ Ctx context.Context
+ Filename string
+ Type string
+ IsWiki bool
+ URLPrefix string
+ Metas map[string]string
+ DefaultLink string
+ GitRepo *git.Repository
+ ShaExistCache map[string]bool
+ cancelFn func()
+ TableOfContents []Header
}
// Cancel runs any cleanup functions that have been registered for this Ctx
diff --git a/modules/templates/helper.go b/modules/templates/helper.go
index cc0fed74422..ef7b70c09f8 100644
--- a/modules/templates/helper.go
+++ b/modules/templates/helper.go
@@ -18,6 +18,7 @@ import (
"reflect"
"regexp"
"runtime"
+ "strconv"
"strings"
texttmpl "text/template"
"time"
@@ -390,6 +391,66 @@ func NewFuncMap() []template.FuncMap {
"Join": strings.Join,
"QueryEscape": url.QueryEscape,
"DotEscape": DotEscape,
+ "Iterate": func(arg interface{}) (items []uint64) {
+ count := uint64(0)
+ switch val := arg.(type) {
+ case uint64:
+ count = val
+ case *uint64:
+ count = *val
+ case int64:
+ if val < 0 {
+ val = 0
+ }
+ count = uint64(val)
+ case *int64:
+ if *val < 0 {
+ *val = 0
+ }
+ count = uint64(*val)
+ case int:
+ if val < 0 {
+ val = 0
+ }
+ count = uint64(val)
+ case *int:
+ if *val < 0 {
+ *val = 0
+ }
+ count = uint64(*val)
+ case uint:
+ count = uint64(val)
+ case *uint:
+ count = uint64(*val)
+ case int32:
+ if val < 0 {
+ val = 0
+ }
+ count = uint64(val)
+ case *int32:
+ if *val < 0 {
+ *val = 0
+ }
+ count = uint64(*val)
+ case uint32:
+ count = uint64(val)
+ case *uint32:
+ count = uint64(*val)
+ case string:
+ cnt, _ := strconv.ParseInt(val, 10, 64)
+ if cnt < 0 {
+ cnt = 0
+ }
+ count = uint64(cnt)
+ }
+ if count <= 0 {
+ return items
+ }
+ for i := uint64(0); i < count; i++ {
+ items = append(items, i)
+ }
+ return items
+ },
}}
}
diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go
index 77f60a1dfaf..f4aabbf480f 100644
--- a/routers/web/repo/wiki.go
+++ b/routers/web/repo/wiki.go
@@ -280,6 +280,8 @@ func renderViewPage(ctx *context.Context) (*git.Repository, *git.TreeEntry) {
ctx.Data["footerPresent"] = false
}
+ ctx.Data["toc"] = rctx.TableOfContents
+
// get commit count - wiki revisions
commitsCount, _ := wikiRepo.FileCommitsCount("master", pageFilename)
ctx.Data["CommitCount"] = commitsCount
diff --git a/templates/repo/wiki/view.tmpl b/templates/repo/wiki/view.tmpl
index 04faa90b9e6..3189ed64caf 100644
--- a/templates/repo/wiki/view.tmpl
+++ b/templates/repo/wiki/view.tmpl
@@ -64,20 +64,39 @@
{{.FormatWarning}}
{{end}}
-