How to use front matter parameter that contains markdown or HTML and turn it into HTML in partials?

Hello everyone

I would like to use nicely formatted text for FAQ schema on some of my posts (bold, italic, list, etc.)

For formatting I will use either HTML or markdown, whatever will work.

I have my FAQ data in front matter for such pages. And then I use shortcodes for displaying it inside the post. This already works nicely.

But for scheme I need to use partials. And here my markdown or html is not formatter correct. The tags are converted to unicode.

<b>This should be bold</b> is formatted to this \u003cb\u003eThis should be bold\u003c/b\u003e

Does anyone know a good solution for using basic html style in json FAQ schema?

Thank you

Yes, this is default Go JSON marshaller.

String values encode as JSON strings coerced to valid UTF-8, replacing invalid bytes with the Unicode replacement rune. So that the JSON will be safe to embed inside HTML tags, the string is encoded using HTMLEscape, which replaces “<”, “>”, “&”, U+2028, and U+2029 are escaped to “\u003c”,“\u003e”, “\u0026”, “\u2028”, and “\u2029”. This replacement can be disabled when using an Encoder, by calling SetEscapeHTML(false).

AFAIK, the only workaround for this is using replace function to modify your JSON string

Did you try safeHTML on the value? The documentation has a JSON sample.

Yes, I forgot to mention that I already tried plainify, markdownify and safeHTML. But to no avail.

Well then, how about doing Markdown in your frontmatter and THEN using markdownify? I am using that procedure and it is definitely working on frontmatter values. If not - show more code, you might have a deeper issue.

Thanks for the suggestion. I will try it out. But I hesitate as it looks like a very ugly solution. I will let you know how it goes.

What if I use Data Files and then integrate it in the partial and the shortcode?

Does it work in both shortcodes and partials? Because for shortcodes it works for me with markdownify.

yes.

And there would be no difference in the handling of content in data-JSON-files and frontmatter-json. It should render the same if the JSON is written the same way.

Here is an example of my front matter (unfortunately is in Slovenian language)

[[faq.section]]
question = "Kdo je avtor AEQ metode?"
answer = """
**AEQ metodo je razvil Aleš Ernst**, z namenom, da svoja osebna odkritja iz vodenja terapij klinične somatike združi pod ime AEQ. 

Podrobnejšo zgodbo o avtorju pa najdete na uradni spletni strani AEQ metode ([za ogled klikni tukaj](https://aeq.si/ustanovitelj-metode/)).
"""

and here is the shortcode

<script type="application/ld+json">
{
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
    {{ with $.Page.Params.faq }}
        {{ $list := .section }}
        {{ $len := len $list }}
        {{ range $index, $element := $list }}
            {
                "@type": "Question",
                "name": "{{ .question | markdownify }}",
                "acceptedAnswer": {
                "@type": "Answer",
                "text": "{{ .answer | markdownify }}"
                {{ print $odgovor }} 
                }
            }
        {{ end }}
    {{ end }}
    ]
}
</script>

If you have any working example at your hand, you can send it to me and I can try that as well. But you are already giving me hope. If markdownify works for you in the partials, then Im more motivated to solve this one.

Aha I found what is causing this. This only happens when I try to use the variable inside the JSON segment of my partial.

Is there some other way how to prepare schema json where the strings wont get encoded in such way?

I thought safeJS solves this.

EDIT: Its Not, when we put it inside " double quotes it’s escaped again. Because Go html/template aware that stuff inside <script> tag.

I think this is the only solution.

{{ `<script type="application/ld+json">` | safeHTML }}
{
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
    {{ with $.Page.Params.faq }}
        {{ $list := .section }}
        {{ $len := len $list }}
        {{ range $index, $element := $list }}
            {
                "@type": "Question",
                "name": "{{ .question | markdownify }}",
                "acceptedAnswer": {
                "@type": "Answer",
                "text": "{{ .answer | markdownify }}"
                {{ print $odgovor }} 
                }
            }
        {{ end }}
    {{ end }}
    ]
}
{{ `</script>` | safeHTML }}
1 Like

Woow great. This looks cleaner than using replace.

Im not skilled enough to know if this approach has any shortcomings. But for now im very satisfied. @pamubay you’re the king. I hope this will help other people that are implementing FAQ sheme.

Yes, Potential to XSS

If you set goldmark unsafe: true.

markup:
  goldmark:
    renderer:
      unsafe: true  
  {{- $content := "**Bold**</script> <script>alert(1)</script> <script> *Italic*" -}}
  {{ `<script type="application/ld+json">` | safeHTML }}
  {
    "xss": "{{ $content | markdownify }}"
  }
  {{ `</script>` | safeHTML }}

In the mean time I also noticed that multiline answers are causing an backslashes as well. Shema validator are saying that JSON is not valid. I will try to replace it, but I dont know how to do that yet.

I returned back to using json and trying to replace chars like this:

{{ $jsonAnswer := .answer | markdownify | jsonify }}
{{ $jsonAnswer := replace $jsonAnswer "\\u003c" "<"}}

This way < is encoded into into /&lt;

It’s a very difficult case for me :smiley:

Maybe I can use Custom output format. What do you think?

Ok. With all the help I finally found a working solution. Here is the code for anyone who wants to use markdown inside JSON schema (such as FAQ structured data)

{{ `<script type="application/ld+json">` | safeHTML }}
{
    "@context": "https://schema.org",
    "@type": "FAQPage",
    "mainEntity": [
    {{ with $.Page.Params.faq }}
        {{ $len := len .section }}
        {{ range $index, $element := .section }}
            {{ $jsonAnswer := .answer | markdownify | jsonify }}
            {{ $jsonAnswer := replace $jsonAnswer "\\u003c" "<"}}
            {{ $jsonAnswer := replace $jsonAnswer "\\u003e" ">"}}
            {
                "@type": "Question",
                "name": "{{ .question | markdownify }}",
                "acceptedAnswer": {
                "@type": "Answer",
                "text": {{ $jsonAnswer | safeHTML }}
                }
            }
            {{ if not (eq (add $index 1) $len) }},{{ end }}
        {{ end }}
    {{ end }}
    ]
}
{{ `</script>` | safeHTML }}

And this is for using front matter like this

[faq]
title = "Just optional title"

[[faq.section]]
question = "What is this?"
answer = "This is **bold** answer"

[[faq.section]]
question = "What is this?"
answer = "This is *italic* answer"

Kudos to @pamubay for generous amount of help.

2 Likes

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.