The .Page variable in my custom render-heading.html hook is sometimes being set to the home page, including its .Title, .Params, etc., so I can’t get access to the current page. I can’t figure out the rule though.
The render hook is in layouts/_default/_markup in my theme.
For pages under /blog it renders correctly (I tried appending {{.Page.Title}} to each heading to check).
I also have a /meta content folder for e.g. my /about page, where I map permalinks to "/:slugorfilename/". For each page in here, the render hook is setting .Page to the home page.
The blog pages also map permalinks to "/:slugorfilename/" so it isn’t that.
I’ve tried running hugo server with --disableFastRender and various other settings, and the bug persists. What am I missing?
That was the first thing I checked. Here is the entire render hook:
<h{{ .Level }} id="{{ .Anchor }}" {{- with .Attributes.class }} class="{{ . }}" {{- end }}>
{{- .Text }}
{{- if and (le .Level 3) .Page.Params.showPermalinks -}}
<a class="heading-anchor accent-icon" href="#{{ .Anchor }}">{{ partial "svg" (dict "name" "link") }}</a>
{{- end -}}
</h{{ .Level }}>
The thing is, in some pages, the .Page value is correct (anything under /blog is working). Elsewhere it is set to the root home page. It isn’t a big website (https://dannorth.net), and the blog is most of the content.
I tried moving some of the buggy pages around, e.g. to the top level, into other folders, etc. Even renaming the file. There is nothing obvious in the front matter for the buggy pages either.
Hi Joe, thanks for this. I just noticed your advice to use .RenderString.
I worked around the problem so I didn’t need the page reference any more, but this markdownify thing is … surprising!
Do you have a reference to how this causes the problem with render hooks? Also, are there any risks you can think of with just replacing markdownify with .RenderString anywhere I have a .Page reference? (Don’t worry, I won’t hold you to it!)
No, as long as the current context (the dot) is the target page. Or to put it another way, blindly replacing markdownify with .RenderString may break things. For example, this won’t work in a shortcode:
{{ "**bold**" | .RenderString }}
You’d need to do this instead:
{{ "**bold**" | .Page.RenderString }}
On several occasions I have unsuccessfully advocated for the deprecation of the markdownify function in favor of the RenderString method. Yes, the ability convert a string of Markdown to HTML without having a page reference is handy, but you need to think carefully about what you’re doing. If you don’t, the rendered page may be incorrect without warning or error, and the problem can be difficult to track down.
My guidance is to always use the RenderString method.
I realised you can blindly replace markdownify with page.RenderString, leaning on the fact that page is always injected as a variable wherever you are in a page context (which is pretty much always, I think!)