gohugoio / hugo

The world’s fastest framework for building websites.
https://gohugo.io
Apache License 2.0
75.73k stars 7.53k forks source link

Scratch and Output Formats #3592

Open sascha53 opened 7 years ago

sascha53 commented 7 years ago

I use partials for inlining svg defs, for example:

{{- $icon_id := "line-chart" -}}
{{- $icon_name := add "icon-" $icon_id -}}
{{- if not (.Scratch.Get $icon_name) -}}{{- .Scratch.Set $icon_name true -}}<svg class="clip" xmlns="http://www.w3.org/2000/svg" width="0" height="0"><defs><svg id="{{ $icon_id }}" xmlns="http://www.w3.org/2000/svg" fill="currentcolor" viewBox="0 0 1792 1792"><path d="M1920 1536v128h-2048v-1536h128v1408h1920zm-128-1248v435q0 21-19.5 29.5t-35.5-7.5l-121-121-633 633q-10 10-23 10t-23-10l-233-233-416 416-192-192 585-585q10-10 23-10t23 10l233 233 464-464-121-121q-16-16-7.5-35.5t29.5-19.5h435q14 0 23 9t9 23z"/></svg></defs></svg>{{- end }}

The goal is to inline a svg defs just once per page, as i reference them with xlink:href. This is what the if statement is made for and that worked well before activating another output format like AMP, which is also using this icon partial in its template.

It seems that the vars defined in Scratch are "reseted" per page, but if you use multiple Output Formats, they are shared and not reseted. The undesired behaviour in my case: Either on the HTML or AMP version of the same page, which is rendered after the other (which is random) the var is already set to true and the svg def isn't rendered.

This also doesn't work:

{{- $id := "facebook" -}}
{{- $name := add "icon-" $id -}}
{{- if lt (.Scratch.Get $name) (len .OutputFormats) -}}
{{- .Scratch.Set $name (add (int (.Scratch.Get $name)) 1) -}}
<svg class="clip" xmlns="http://www.w3.org/2000/svg" width="0" height="0">
<defs>
<svg viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg" id="{{ $id }}" fill="currentcolor"><path d="M1343 12v264h-157q-86 0-116 36t-30 108v189h293l-39 296h-254v759h-306v-759h-255v-296h255v-218q0-186 104-288.5t277-102.5q147 0 228 12z"/></svg>
</defs>
</svg>
{{- end }}

The solution would be either a proper reset of the Scratch vars for every Output Format. Or a page variable that tells me which output format is currently rendered (or extension) and that i can use in an if statement. Or maybe something else.

stale[bot] commented 5 years ago

This issue has been automatically marked as stale because it has not had recent activity. The resources of the Hugo team are limited, and so we are asking for your help. If this is a bug and you can still reproduce this error on the master branch, please reply with all of the information you have about it in order to keep the issue open. If this is a feature request, and you feel that it is still relevant and valuable, please tell us why. This issue will automatically be closed in the near future if no further activity occurs. Thank you for all your contributions.

swamidass commented 2 years ago

This is a breaking change for setups that use Scratch to communicate between templates.

For communication between output-formats, it is necessary for Scratch to persist between output formats. There is no good fix for this if the current behavior is changed. In contrast, the OP's use case can be addressed with the current system with this code.

In the head of each template:

{{ .Scratch.Set "RenderedIcons" (slice ) }} And then for each icon:

{{- $icon_id := "line-chart" -}} {{ if in (.Scratch.Get "RenderedIcons" ) $icon_id }} // output svg {{ .Scratch.Add "RenderedIcons" (slice $icon_id) }} {{ else }} // output ref to svg {{ end }}

It is easy to flush portions of the cache manually, but hard to communicate persistently across live-reloads and templates, etc. Making Scratch more ephemeral is a breaking change, though making it more persistent (especially persistence between runs) increases its utility.

For this reason, I do not think this change should be made.