stackbuilders / stache

Mustache templates for Haskell
MIT License
28 stars 10 forks source link

Interpolation with {{{ does not encode Strings correctly #103

Closed pbrisbin closed 4 months ago

pbrisbin commented 4 months ago

My understanding is that {{{ interpolation (vs {{) should interpolate a JSON-encoded value with no escaping.

Therefore, I'd expect:

country: {{{settings.country}}}

(Where country is a Text or String type)

To produce,

country: "No"

Because,

λ> import Data.Aeson
λ> encode "No"
"\"No\""

Instead, it produces:

country: No

This is Bad because, as we all know, it will be interpreted as a boolean False by most Yaml parsers.

I could work around this, with something like:

country: '{{{settings.country}}}'

But that doesn't work for my use-case, which is CloudFormation templates, where I might be interpolating the string "No", but also a complex object like { Ref: "Country" }. So if I added quotes to fix this case, I would produce the wrong thing in that case instead,

country: '{"Ref": "Country"}'

I need that case, to still come out as:

country: {"Ref": "Country"}

Which is why I'm using {{{country}}} in the first place.

It just seems strings are not being handled correctly.

mrkkrp commented 4 months ago

The difference between {{{ and {{ is the lack of HTML-escaping, not any other type of escaping. See https://mustache.github.io/mustache.5.html. Automatic quoting of strings with either {{{ or {{ is contrary to the specification: https://github.com/mustache/spec/blob/master/specs/interpolation.yml#L156-L160. You probably need to prepare your values manually (encode as ByteString or Text) before you interpolate them.

pbrisbin commented 4 months ago

Thanks for clarifying!

You probably need to prepare your values manually (encode as ByteString or Text) before you interpolate them

Can you expand on this a bit? Do you mean take a value like "No" :: Text and make it "\"No\"" :: Text before interpolating it?

mrkkrp commented 4 months ago

What I had in mind is that if you have a JSON value you need to "pre-render" it (so that strings get their quoting, while objects remain correctly represented between curly braces {}) and then pass the result of rendering into the template for interpolation instead of expecting stache to do JSON rendering for you automatically.

pbrisbin commented 4 months ago

Yeah, I think we're saying very similar things. That was my workaround while awaiting this Issue anyway, so I guess I'll just keep it.