Combining string functions (e.g. title) with safeHTML

Given a string with HTML, such as
{{ $input := "<span style="color:blue">hello world!</span>" }}

And then using either safeHTML (or page.RenderString)
{{ $input | safeHTML }} outputs a blue “hello world!”

But when you add either title (or strings.Title), the output will only apply one of them. For example:
{{ title $input | safeHTML }} outputs a black “Hello World!” (in Title Case, but dropped the HTML)
{{ (title $input) | safeHTML }} outputs “<Span Style="Color:Blue">Hello World!</Span>” as text
{{ title ($input | safeHTML) }} outputs “<Span Style="Color:Blue">Hello World!</Span>” as text
{{ ($input | safeHTML) | title }} outputs “<Span Style="Color:Blue">Hello World!</Span>” as text
{{ $input | safeHTML | title }} outputs “<Span Style="Color:Blue">Hello World!</Span>” as text

For what it’s worth, this also applies to other string functions such as lower humanize etc.

Do you have any suggestions for combining these two functions?

This:

{{ $input := `<span style="color:blue">hello world!</span>` }}
{{ $input | title | safeHTML }}

produces this:

image

This:

{{ $text := "hello world!" }}
{{ printf `<span style="color:blue">%s</span>` ($text | title) | safeHTML }}

produces this:

image

Passing the entire HTML span element through the title template function is non-sensical.

Passing the entire HTML span element through the title template function is non-sensical.

I agree that in most situations, it wouldn’t make sense to pass an element through. Why not just manipulate the text, then apply the HTML? I created the example to make things simpler, but in our case, strings are from i18n strings need spans around different words or links in side of them as HTML or Markdown.

Perhaps it’s bad practice to use HTML or Markdown in i18n strings? It generally works fine with (page.RenderString, markdownify, or safeHTML). We couldn’t come up with a way to have different HTML applied across different languages. e.g. CSS to specific words or an ID to specific parts or inserting line breaks.

That’s why we’d want HTML to be applied first, then the output manipulated. While we try to input the right capitalizations, we were looking to force it programmatically.

So perhaps a better string example would have been
english in en.toml

[redDog]
other = "<span style="color:red">red</span><br /> dog`"

Spanish in es.toml

[redDog]
other = "perro <br /><span style="color:red">rojo</span>"

Then in the layout
{{ title (i18n "redDog" | safeHTML }} or similar versions from the original post

No, it’s not a bad practice. Your problem is capitalization; it is applied to the entire translated string, not just the non-HTML.

I suggest you either capitalize your string in the translation table, or find another way.

This is ugly, but does what you want.

i18n/es.toml

[red_dog]
html_pattern = '%s <br><span style="color:red">%s</span>'
noun = 'perro'
adjective = 'rojo'

template

{{ printf (T "red_dog.html_pattern") (T "red_dog.noun" | title) (T "red_dog.adjective" | title) | safeHTML }}

result (HTML)

Perro <br><span style="color:red">Rojo</span>

result (in browser)

image

1 Like