Thinking about this, this should not be too hard (but a fair amount of work) and would have a fair amount of use cases.
So from a template:
{{ $img := .Site.Resource "images/mylogo.png" }}
(or maybe just a template func with a shorter name)
Could look for that image in
And create a proper Image that can be resized etc. This is a metadata-less resource by design (at least in its first iteration).
This also opens up a set of interesting use cases.
{{ $css := .Site.Resource "css/main.css" }}
{{ $css := $css.FingerPrint }}
See #4268
See https://discourse.gohugo.io/t/any-plan-to-add-resize-feature-to-any-image-object/10358/13
Most likely just ran into one of these use cases:
single.html -> calls partial.html
Within single.html {{ range .Resources }} is used, which then provides data to the partial {{ partial "partial.html" . }}.
A few issues come up then.
Current workaround using scratch:
single.html:
{{ range sort .Resources }}
{{ $.Scratch.Set "data" . }}
{{ partial "fragments/test.html" $ }}
{{ end }}
fragments/test.html:
{{ $self := ($.Scratch.Get "data").Params }}
{{ $name := ($.Scratch.Get "data").Name }}
{{ $name_t := strings.TrimSuffix ".md" $name }}
{{ $content := .Resources.Match (printf "%s/*" $name_t) }}
{{ range $content }}
{{ .Params }}
{{ end }}
@stp-ip no, I think you have a syntax problem. Try https://discourse.gohugo.io/
@regisphilibert @kaushalmodi @moorereason and gang:
I have pondered on a flexible design on this that do this in a decoupled way (makes adding new stuff easy) without creating these big interfaces/structs.
Here are my thoughts using an example:
$css := resource "main.css" | resource.Digest | resource.Fingerprint
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Digest | base64Encode }}">
Notes:
The above chain (compose) the resources and differentiates between simple decorator filters (digest) and filters that changes the destination/permalink (fingerprint). It must be ordered, but we could probably handle missing steps (below: we need the digest to create the fingerprint, so just create a default one):
$css := resource "main.css" | resource.Fingerprint
This will, of course, be possible to use on the bundle resources we know today (not sure about the Page resource, but ...), so this would work:
$image := .Resources.GetMatch "*featured*" | resource.Digest | resource.Fingerprint
I will probably implement the above example as a proof of concept (it has its use) and will add options to select sha256 (default) etc.
And as always: Name suggestions/improvements are always welcome.
Out of scope in this topic, but with a little imagination one could envision:
$css := resource "main.scss" | resource.Sassify | resource.Digest | resource.Fingerprint
...
This looks great, let get back to you shortly!
$css := resource "main.css" | resource.Digest | resource.Fingerprint
I looked at the PR, but still couldn't understand what .Digest and .Fingerprint do.. Can you provide a 1-line summary for each function?
The above chain (compose) the resources and differentiates between simple decorator filters (digest) and filters that changes the destination/permalink (fingerprint).
This too did not help me understand those, sorry.
$css := resource "main.scss" | resource.Sassify | resource.Digest | resource.Fingerprint
I have comment about .Sassify :) Anything foo-ify implies that the outcome will be foo. Let me explain with few examples (ref):
beautify, mystify, simplify
Above, they mean: make beautiful, make mysterious, make simple.
Going along the same lines .Sassify would mean, make .sass or .scss. But based on the context, it looks like it is converting .scss to a .css? I have similar reservations for the current markdownify method, because it does not output a markdown string but rather markdown converted to HTML.
So.. given we we have a transform library, would transform.toCSS be a better name. I know that name is yet hypothetical, but I thought of commenting before it gets baked in like markdownify. :)
.Digest and .Fingerprint
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Digest | base64Encode }}">
Becomes
<link rel="stylesheet" href="main-88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589.css" integrity="ODhkNDI2NmZkNGU2MzM4ZDEzYjg0NWZjZjI4OTU3OWQyMDljODk3ODIzYjkyMTdkYTNlMTYxOTM2ZjAzMTU4OQ==">
That is the main use case of .Digest and .Fingerprint.
But I think it is best to focus on the concept here and not dig into the details of the "proof of concept". The "sassify" is just added to give some context, but I see that it can be confusing if you don't see the bigger picture.
I really like this. 馃
The initial title seemed to only add current Page Resources package to the .Site context. Now it seems this issue has broaden to adding a template function which allows to pipe resource operation/methods on a resource (from Page Bundle or static dir).
I guess the resource function will be available to both static dir resources AND page bundle resources (as it was the initial direction of this issue), yet, it only take one parameter: a relative path.
Will the function first look for this path in the page bundle or the static dir ? Or is this reserved to the static dir ?
Out of scope in this topic, but with a little imagination one could envision:
$css := resource "main.scss" | resource.Sassify | resource.Digest | resource.Fingerprint
Out of scope and yet, it's all I can think about... Being able to build your site without a build tool (and its dependencies), would make Hugo quiet a unique static gen. This would mean theme dev would not have to deal with a compiled css file ever. So wouldn't theme users... I would gladly fallback on whatever css/js preprocessor library is built in with Hugo (one per language would be enough I think) in order to benefit from this enhancement.
Now it seems this issue has broaden to adding a template function which allows to pipe resource operation/methods on a resource (from Page Bundle or static dir).
The resource func concept is the same as before I changed the title. I just changed it from a method to a function. That func is just relevant for non-bundled resources (ad-hoc resources, as I would call it; static resources maybe. I will certainly look in /static (both project and theme)). It _creates a Resource_, that is not needed in the "bundle case". But the bundled resources can, of course, use the other resource funcs (see below).
Out of scope and yet, it's all I can think about...
$css := resource "main.scss" | resource.Sassify | resource.Minify | resource.Digest | resource.Fingerprint
This PR will at least add the building blocks to get there. I see lots of Hugo sites with fairly complex Gulp/Grunt setups just to do the above. So it is a tempting setup.
$css := resource "main.scss" | resource.Sassify | resource.Minify | resource.Digest | resource.Fingerprint
This syntax seems very verbose. The Sassify and Minify syntax makes sense, but needing an additional 2 function calls to process the SRI data feels unnecessary?
The Sassify and Minify syntax makes sense, but needing an additional 2 function calls to process the SRI data feels unnecessary?
It would be good if you could provide an improved alternative.
My thought here is to have small and decoupled funcs doing one thing. Use what you want.
I could do
$css := resource "main.scss" | resource.Sassify true true true true
But that would loose lots of flexibility and is hardly easy to read.
It may help to give more examples:
$css := resource "main.scss" | resource.Sassify | resource.Minify | resource.Digest | resource.Fingerprint
$js := resource "main.js" | resource.Minify | resource.Digest | resource.Fingerprint
$imageLink := .Resources.GetMatch "foo" | resource.Digest
You can make it more readable by splitting in lines:
$css := resource "main.scss" | resource.Sassify | resource.Minify
$css := $css | resource.Digest | resource.Fingerprint
I was thinking something more along the lines of:
$css := resource "main.scss" | resource.Sassify
<link rel="stylesheet" href="{{ $css.RelPermalink }}" integrity="{{ $css.Digest | base64Encode }}">
ie that the .Digest etc properties are always accessible, perhaps without actually computing them until necessary
ie that the .Digest etc properties are always accessible, perhaps without actually computing them until necessary
Which works great for type-specific properties ($image.Width), but for cross-cutting resource functions (digest) I see now way to get what you want without adding God-like classes and interfaces with hard-to understand lazy loading. I suspect this will be more obvious with more exotic "resource filters" that only some would want to use in some cases. But if you have a clean way of implementing this, I'm open ears.
I would disagree with only one thing that @regisphilibert said: "[These changes] would make Hugo quiet a unique static gen." I see these changes more as bringing Hugo in line with Jekyll, which already has a reasonably robust static asset story via plugins (though using the asset pipeline involves a big performance hit). Everything else you say is spot on.
Something I do like about Jekyll (though I now avoid using it) is that you can run jekyll serve without needing to run a parallel Webpack/Gulp/whatever JavaScript Frankenstack. One of the barriers to Hugo adoption that I've encountered in the real world is that people are skittish about such Frankenstacks and requiring developers to install a multi-lingual tool chain "just to build a website." If Hugo provides even a basic resource pipeline like this, the current "hard sell" that I've had to make instantly becomes a no-brainer.
I do see a potential risk of feature bloat, with some users wanting Hugo to fully supplant the entirety of their complex front-end setup. But on the other hand, my experience suggests that a small handful of processing functions鈥擲ass/Less to CSS, sourcemaps, JavaScript uglification鈥攃ould cover a huge chunk of use cases.
In terms of interface, I have no objections to the basic approach presented at the beginning of the thread. I'm fine with the verbosity if it means more transparency.
So bringing this back to where it all began :) (for me at least)
Would this be possible:
{{ $img := resource "header.jpg" | resource.Resize "700x" }}
<header>
<img src="{{ $img.RelPermalink }}" alt="">
</header>
@lucperkins I did not want to derail the issue thread. Can't wait to discuss it with you when moving closer to this other issue though :)
I see these changes more as bringing Hugo in line with Jekyll
There is, of course, the speed, which may bring us slightly ahead.
I do see a potential risk of feature bloat, with some users wanting
This limits itself naturally I think.
Which cover lots of use cases.
{{ $img := resource "header.jpg" | resource.Resize "700x" }}
You would have to do this:
{{ $img := (resource "header.jpg").Resize "700x" }}
Most helpful comment
@regisphilibert @kaushalmodi @moorereason and gang:
I have pondered on a flexible design on this that do this in a decoupled way (makes adding new stuff easy) without creating these big interfaces/structs.
Here are my thoughts using an example:
Notes:
The above chain (compose) the resources and differentiates between simple decorator filters (digest) and filters that changes the destination/permalink (fingerprint). It must be ordered, but we could probably handle missing steps (below: we need the digest to create the fingerprint, so just create a default one):
This will, of course, be possible to use on the bundle resources we know today (not sure about the Page resource, but ...), so this would work:
I will probably implement the above example as a proof of concept (it has its use) and will add options to select sha256 (default) etc.
And as always: Name suggestions/improvements are always welcome.
Out of scope in this topic, but with a little imagination one could envision: