Skip to content

Commit 44539bc

Browse files
committed
markup/tableofcontents: Add pre/post config options
Add Pre and Post configuration options to customize the HTML wrapper around the table of contents. This allows users to add custom elements like headings for accessibility. Example config: [markup.tableOfContents] pre = '<nav id="TableOfContents"><h2>Contents</h2>' post = '</nav>' The pre/post parameters are optional in ToHTML() for backward compatibility - existing templates continue to work without changes. Fixes #8338
1 parent b1f7e35 commit 44539bc

File tree

2 files changed

+30
-3
lines changed

2 files changed

+30
-3
lines changed

‎hugolib/page__content.go‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,8 @@ func (c *cachedContentScope) contentToC(ctx context.Context) (contentTableOfCont
670670
cfg.TableOfContents.StartLevel,
671671
cfg.TableOfContents.EndLevel,
672672
cfg.TableOfContents.Ordered,
673+
cfg.TableOfContents.Pre,
674+
cfg.TableOfContents.Post,
673675
)
674676
return err
675677
}

‎markup/tableofcontents/tableofcontents.go‎

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ func (toc *Fragments) addAt(h *Heading, row, level int) {
148148
}
149149

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

167+
// Use default pre/post values if not provided
168+
pre := DefaultConfig.Pre
169+
post := DefaultConfig.Post
170+
if len(prePost) > 0 && prePost[0] != "" {
171+
pre = prePost[0]
172+
}
173+
if len(prePost) > 1 && prePost[1] != "" {
174+
post = prePost[1]
175+
}
176+
166177
b := &tocBuilder{
167178
s: strings.Builder{},
168179
h: toc.Headings,
169180
startLevel: iStartLevel,
170181
stopLevel: iStopLevel,
171182
ordered: ordered,
183+
pre: pre,
184+
post: post,
172185
}
173186
b.Build()
174187
return template.HTML(b.s.String()), nil
@@ -187,16 +200,18 @@ type tocBuilder struct {
187200
startLevel int
188201
stopLevel int
189202
ordered bool
203+
pre string
204+
post string
190205
}
191206

192207
func (b *tocBuilder) Build() {
193208
b.writeNav(b.h)
194209
}
195210

196211
func (b *tocBuilder) writeNav(h Headings) {
197-
b.s.WriteString("<nav id=\"TableOfContents\">")
212+
b.s.WriteString(b.pre)
198213
b.writeHeadings(1, 0, b.h)
199-
b.s.WriteString("</nav>")
214+
b.s.WriteString(b.post)
200215
}
201216

202217
func (b *tocBuilder) writeHeadings(level, indent int, h Headings) {
@@ -260,6 +275,8 @@ var DefaultConfig = Config{
260275
StartLevel: 2,
261276
EndLevel: 3,
262277
Ordered: false,
278+
Pre: `<nav id="TableOfContents">`,
279+
Post: "</nav>",
263280
}
264281

265282
type Config struct {
@@ -274,4 +291,12 @@ type Config struct {
274291

275292
// Whether to produce a ordered list or not.
276293
Ordered bool
294+
295+
// Pre is the HTML to insert before the ToC list.
296+
// Default is `<nav id="TableOfContents">`.
297+
Pre string
298+
299+
// Post is the HTML to insert after the ToC list.
300+
// Default is `</nav>`.
301+
Post string
277302
}

0 commit comments

Comments
 (0)