I’ve had a look around and haven’t had any luck finding this out.
Markdown articles will sometimes contain <h1> elements that may clash with the page being rendered (where an <h1> for the article section would be used for the post title, for instance).
Is there an option or setting to force all headings in a post to start at a certain level (that is, all headings in a post now begin at <h2>, even if they were created as <h1> / # elements)?
I do a number of other changes to Markdown rendering in that post, so let me break out just the part you need.
We will create a partial template called contentShiftHeadings.html with the following code:
{{/* get the Markdown without front matter */}}
{{ $s := .RawContent }}
{{/* the regex of start of line `^` doesn't work. (GoLang has a subset of regex)
Need to specify newlines via `\n`
Need to ensure newlines at start and end of content */}}
{{ $s := delimit (slice "\n" $s "\n") "" }}
{{/* search for any Markdown headings `#` at start of line
and add another `#` to start of line. NOTE: we could increment by more `#` here. */}}
{{ $s := $s | replaceRE "\n(#+) " "\n#$1 " }}
{{/* render the Markdown to HTML
declare it to be safe HTML and return */}}
{{ $s := $s | markdownify }}
{{ $s := $s | safeHTML }}
{{ $s }}
In all templates replace {{ .Content }} with {{ partial "contentShiftHeadings.html" . }} You may want to refer to the documentation about Partial Templates
This works very well for me.
But there are potential problems:
No shortcodes in the content. RawContent bypasses rendering shortcodes and I didn’t find a way to tigger shortcode rendering later. This doesn’t affect me, but I would prefer not to take away features.
I don’t know your full use case, but have you considered scripting this against the content files themselves rather than relying on Hugo to do it every single time you build your site? Is there a reason you need# in your content when likely ## is more semantic?
I can’t speak for @patdavid but I have a several reasons for shifting headings.
I feel the default should be that individual Markdown pages should be able to stand alone and content rooted at #
It can depend on context. Are you viewing at a single page or something composed of multiple pages: Sections, Chapter, or Book or a home page that lists the entire content of the last 10 postings.
A number of Markdown editor tools treat heading structures as Tables of Content for navigation or provide outliner functionality. It is better to work with pages rooted at #
Allow writers to not worry about these technical details which can be automated.
I write almost every thing in Markdown. It might end out posted to a blog, exported to MS Word or PDF, copied and pasted into an email, made into a Presentation. Consistent use of starting with # makes it easier to build workflows to wherever the content gets sent.
---
title: bald eagle
---
# Actually not bald
…
# Cooler than turkeys
…
I’d have it generate a page that uses sectioning elements like article and section like so:
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="UTF-8" />
<title>allbirds.local</title>
</head>
<body>
<h1>allbirds.local — your local guide for all birds!</h1>
<article>
<h1>bald eagle</h1>
<section>
<h1>Actually not bald</h1>
…
<h1>Cooler than turkeys</h1>
…
</section>
</article>
</body>
</html>
And conformance checkers (but not, alas, anything designed for blind people — nobody’s put a fire under the people who make VoiceOver and JAWS yet) would realize the outline looks like this:
- allbirds.local — your local guide for all birds!
- bald eagle
- Actually not bald
- Cooler than turkeys
Sorry for my late response, was busy working on other things for the site.
Yes, all of the reasons as enumerated by @leejoramo are reasons I also asked my question in the first place.
In particular, authors shouldn’t have to worry about this. Just let them write valid, stand-alone markdown posts. In this case it’s perfectly natural for them to start headings at # in their doc. Or, they are cognizant that the title may be the <h1> and as such start all of their markdown headings at ##.
Hi, I know this is an ancient topic, but since issue 6373 went nowhere, this is the next best thing I could found.
Thank you so much for this extremely insightful code. I have made a couple of changes to get it work with shortcodes and (layout-specific) render hooks.
{{/* get the Markdown without front matter */}}
{{- $s := .content -}}
{{- /* the regex of start of line `^` doesn't work. (GoLang has a subset of regex)
Need to specify newlines via `\n`
Need to ensure newlines at start and end of content */ -}}
{{- $s = delimit (slice "\n" $s "\n") "" -}}
{{- /* search for any Markdown headings `#` at start of line
and add another `#` to start of line. NOTE: we could increment by more `#` here. */ -}}
{{- $s = $s | replaceRE `\n(#+) ` `#$1 ` -}}
{{- /* render the Markdown to HTML
declare it to be safe HTML and return */ -}}
{{- $s = $s | .page.RenderString -}}
{{ $s }}
And in place of {{ .Content }}, call the partial with {{ partial "contentShiftHeadings.html" (dict "page" . "content" .RawContent) }}