I have a layout which creates some dynamic javascript variable data using newScratch.
The problem is each call to the scratch’s Set method is outputting double quotes ("").
A simplified example, having:
{{ define "foot" }}
<script>
A
{{ $scratch := newScratch }}
{{ $scratch.Set "greeting" "Hello" }}
B
</script>
{{ end }}
will actually output:
<script>
A
""
B
</script>
which is causing issues in my actual code:
{{ define "foot" }}
<script>
{{- $constructorsData := slice -}}
{{- range $constructor := sort $.Site.Data.constructors "name" -}}
{{- $country := index $.Site.Data.countries $constructor.countryId -}}
{{- $constructorData := newScratch -}}
{{- $constructorData.Set "id" $constructor.id -}}
{{- $constructorData.Set "name" $constructor.name -}}
{{- $constructorData.Set "countryAlpha2Code" $country.alpha2Code -}}
{{- $constructorData.Set "countryAlpha3Code" $country.alpha3Code -}}
{{- $constructorData.Set "countryName" $country.name -}}
{{- $constructorsData = $constructorsData | append ($constructorData.Values) -}}
{{- end -}}
var constructorsData = {{ $constructorsData }};
..
</script>
{{ end }}
as the var constructorsData = [..]; output in the generated page has a lot of "" prepended to it, making the javascript invalid.
Note I was experimenting a bit and when I just remove the opening <script> tag, the "" are not outputted anymore…
Am I doing something wrong here as I don’t understand why the ""s are outputted…?
Note until now I was not having any issue without using a Scratch.
I currently have (which is working):
{{ define "foot" }}
<script>
{{- $constructorsData := slice -}}
{{- range $constructor := sort $.Site.Data.constructors "name" -}}
{{- $country := index $.Site.Data.countries $constructor.countryId -}}
{{- $constructorData := (dict "id" $constructor.id) -}}
{{- $constructorData = merge $constructorData (dict "name" $constructor.name) -}}
{{- $constructorData = merge $constructorData (dict "countryAlpha2Code" $country.alpha2Code) -}}
{{- $constructorData = merge $constructorData (dict "countryAlpha3Code" $country.alpha3Code) -}}
{{- $constructorData = merge $constructorData (dict "countryName" $country.name) -}}
{{- $constructorsData = $constructorsData | append ($constructorData) -}}
{{- end -}}
var constructorsData = {{ $constructorsData }};
..
</script>
{{ end }}
I only wanted to replace all this dict merging by using a Scratch…
pamubay
December 30, 2020, 11:26pm
3
you could write it like this
{{ `<script>` | safeHTML }}
A
{{ $scratch := newScratch }}
{{ $scratch.Set "greeting" "Hello" }}
B
{{ `</script>` | safeHTML }}
So Go Templates parser will not detect the <script> tag and not doing any escaping inside the tag.
Thanks it works! Now I’m wondering what the Go Templates engine does when detecting the <script> tag…
For future readers,
another simple solution is just to define the Scratch outside the <script> tag.
{{ define "foot" }}
{{- $constructorsData := slice -}}
{{- range $constructor := sort $.Site.Data.constructors "name" -}}
{{- $country := index $.Site.Data.countries $constructor.countryId -}}
{{- $constructorData := newScratch -}}
{{- $constructorData.Set "id" $constructor.id -}}
{{- $constructorData.Set "name" $constructor.name -}}
{{- $constructorData.Set "countryAlpha2Code" $country.alpha2Code -}}
{{- $constructorData.Set "countryAlpha3Code" $country.alpha3Code -}}
{{- $constructorData.Set "countryName" $country.name -}}
{{- $constructorsData = $constructorsData | append ($constructorData.Values) -}}
{{- end -}}
<script>
var constructorsData = {{ $constructorsData }};
..
</script>
{{ end }}
bep
December 31, 2020, 11:02am
6
Set returns an empty string, not double quotes, so the quotes comes from “somewhere else”.
You can try
{{- $scratch.Set “greeting” “Hello” -}}
To trim the newlines.
I would discourage following the accepted solution of trying to completely bypassing the template engine’s security model. The correct solution is to use safeJS.
<script>
{{ $scratch.Set "greeting" "Hello" | safeJS }}
</script>
I don’t recall why we do this, but Set returns an empty string. Bare strings are considered unsafe in a <script> context, so the template engine quotes and escapes the string for Javascript.