Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions hugolib/page__content.go
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,8 @@ func (c *cachedContentScope) contentToC(ctx context.Context) (contentTableOfCont
cfg.TableOfContents.StartLevel,
cfg.TableOfContents.EndLevel,
cfg.TableOfContents.Ordered,
cfg.TableOfContents.Pre,
cfg.TableOfContents.Post,
)
return err
}
Expand Down
31 changes: 28 additions & 3 deletions markup/tableofcontents/tableofcontents.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ func (toc *Fragments) addAt(h *Heading, row, level int) {
}

// ToHTML renders the ToC as HTML.
func (toc *Fragments) ToHTML(startLevel, stopLevel any, ordered bool) (template.HTML, error) {
// The pre and post parameters are optional and default to the nav wrapper if not provided.
func (toc *Fragments) ToHTML(startLevel, stopLevel any, ordered bool, prePost ...string) (template.HTML, error) {
if toc == nil {
return "", nil
}
Expand All @@ -163,12 +164,24 @@ func (toc *Fragments) ToHTML(startLevel, stopLevel any, ordered bool) (template.
return "", fmt.Errorf("stopLevel: %w", err)
}

// Use default pre/post values if not provided
pre := DefaultConfig.Pre
post := DefaultConfig.Post
if len(prePost) > 0 && prePost[0] != "" {
pre = prePost[0]
}
if len(prePost) > 1 && prePost[1] != "" {
post = prePost[1]
}

b := &tocBuilder{
s: strings.Builder{},
h: toc.Headings,
startLevel: iStartLevel,
stopLevel: iStopLevel,
ordered: ordered,
pre: pre,
post: post,
}
b.Build()
return template.HTML(b.s.String()), nil
Expand All @@ -187,16 +200,18 @@ type tocBuilder struct {
startLevel int
stopLevel int
ordered bool
pre string
post string
}

func (b *tocBuilder) Build() {
b.writeNav(b.h)
}

func (b *tocBuilder) writeNav(h Headings) {
b.s.WriteString("<nav id=\"TableOfContents\">")
b.s.WriteString(b.pre)
b.writeHeadings(1, 0, b.h)
b.s.WriteString("</nav>")
b.s.WriteString(b.post)
}

func (b *tocBuilder) writeHeadings(level, indent int, h Headings) {
Expand Down Expand Up @@ -260,6 +275,8 @@ var DefaultConfig = Config{
StartLevel: 2,
EndLevel: 3,
Ordered: false,
Pre: `<nav id="TableOfContents">`,
Post: "</nav>",
}

type Config struct {
Expand All @@ -274,4 +291,12 @@ type Config struct {

// Whether to produce a ordered list or not.
Ordered bool

// Pre is the HTML to insert before the ToC list.
// Default is `<nav id="TableOfContents">`.
Pre string

// Post is the HTML to insert after the ToC list.
// Default is `</nav>`.
Post string
}