Hugo 0.55.* breaks structured data rendering

I’m trying to add JSON-LD Structured Data to my site, and in 0.54 was using this template without issue:

<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@type": "WebSite",
    "name": "{{ $.Site.Title }}",
    {{- with site.Params.alternatePageName }}"alternateName": "{{ . }}",{{- end }}
    "url": "{{ $.Site.BaseURL }}"
}
</script>

This was rendering as:

<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@type": "WebSite",
    "name": "Ample",
    "url": "http://localhost:1313/"
}
</script>

But in 0.55.* (including latest DEV) it’s rendering with the URL slashes escaped:

<script type="application/ld+json">
{
    "@context": "http://schema.org",
    "@type": "WebSite",
    "name": "Ample",
    "url": "http:\/\/localhost:1313\/"
}
</script>

However all other templates referencing the same URL render perfectly fine, it’s seemingly only templates that are inside the <script> tag that have the issue. And no amount of | safeURL etc seems to fix the issue.

Also nested structured data templates are rendering with newline characters intact (so the entire template in a single line with \n characters).

Found my own fix, though it’s a rather painful workaround.

I now have two partial templates: the first provides the actual structured data:

{
    "@context": "http://schema.org",
    "@type": "WebSite",
    "name": "{{ $.Site.Title }}",
    {{- with site.Params.alternatePageName }}"alternateName": "{{ . }}",{{- end }}
    "url": "{{ $.Site.BaseURL }}"
}

The second invokes the first and uses safeJS on the contents:

<script type="application/ld+json">
{{ partial "seo/website" . | safeJS }}
</script>

This at least gets me back to working, though it dramatically increases the number of partials I have to have lying around.

5 Likes

As an alternative: Formatting URL's in JSON string

That works for the specific case of an inline URL, but doesn’t seem to work at all for nested structured data, while piping the top level partial through safeJS does seem to work.

That’s pretty much the use case of the topic I linked to as well.

I don’t see any nesting within that topic, at least not like I’m doing where there’s an embedded partial call that brings in another bit of structured data that itself might have URLS.

If I use the above trick to fix the URL the resulting partial still comes back all in a single line with newlines intact. If I mark the partial call as safeJS then it’s no longer in a single line, but it’s full of improperly encoded characters and the URL is screwed up again.

Only if I do not apply the | jsonify | safeJS fix to any of the partials, remove the <script> tags to the root template, and then mark the partial call that builds the whole nested JSON-LD tree and pipes it through safeJS do I get a properly rendered structure.

Thank you for this solution/workaround! I was quite stuck. I hope this is not necessary in future versions of Hugo.

Brillant !!! Thanks a lot I was running crazy. Still efficient in 0.61.0