aboutsummaryrefslogtreecommitdiffhomepage
path: root/content/en/functions/resources
diff options
context:
space:
mode:
Diffstat (limited to 'content/en/functions/resources')
-rw-r--r--content/en/functions/resources/Babel.md88
-rw-r--r--content/en/functions/resources/ByType.md34
-rw-r--r--content/en/functions/resources/Concat.md21
-rw-r--r--content/en/functions/resources/Copy.md32
-rw-r--r--content/en/functions/resources/ExecuteAsTemplate.md56
-rw-r--r--content/en/functions/resources/Fingerprint.md42
-rw-r--r--content/en/functions/resources/FromString.md71
-rw-r--r--content/en/functions/resources/Get.md30
-rw-r--r--content/en/functions/resources/GetMatch.md36
-rw-r--r--content/en/functions/resources/GetRemote.md177
-rw-r--r--content/en/functions/resources/Match.md36
-rw-r--r--content/en/functions/resources/Minify.md23
-rw-r--r--content/en/functions/resources/PostCSS.md129
-rw-r--r--content/en/functions/resources/PostProcess.md160
-rw-r--r--content/en/functions/resources/ToCSS.md224
-rw-r--r--content/en/functions/resources/_common/_index.md12
-rw-r--r--content/en/functions/resources/_common/postcss-windows-warning.md8
-rw-r--r--content/en/functions/resources/_index.md12
18 files changed, 1191 insertions, 0 deletions
diff --git a/content/en/functions/resources/Babel.md b/content/en/functions/resources/Babel.md
new file mode 100644
index 000000000..57ddb7d23
--- /dev/null
+++ b/content/en/functions/resources/Babel.md
@@ -0,0 +1,88 @@
+---
+title: resources.Babel
+description: Compiles the given JavaScript resource with Babel.
+categories: []
+keywords: []
+action:
+ aliases: [babel]
+ related:
+ - functions/js/Build
+ - functions/resources/Fingerprint
+ - functions/resources/Minify
+ returnType: resource.Resource
+ signatures: ['resources.Babel [OPTIONS] RESOURCE']
+toc: true
+---
+
+```go-html-template
+{{ with resources.Get "js/main.js" }}
+ {{ if hugo.IsDevelopment }}
+ {{ with . | babel }}
+ <script src="{{ .RelPermalink }}"></script>
+ {{ end }}
+ {{ else }}
+ {{ $opts := dict "minified" true }}
+ {{ with . | babel $opts | fingerprint }}
+ <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script>
+ {{ end }}
+ {{ end }}
+{{ end }}
+```
+
+## Setup
+
+Step 1
+: Install [Node.js](https://nodejs.org/en/download)
+
+Step 2
+: Install the required Node.js packages in the root of your project.
+
+```sh
+npm install --save-dev @babel/core @babel/cli
+```
+
+Step 3
+: Add the babel executable to Hugo's `security.exec.allow` list in your site configuration:
+
+{{< code-toggle file=hugo >}}
+[security.exec]
+ allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^npx$', '^postcss$', '^babel$']
+{{< /code-toggle >}}
+
+## Configuration
+
+We add the main project's `node_modules` to `NODE_PATH` when running Babel and similar tools. There are some known [issues](https://github.com/babel/babel/issues/5618) with Babel in this area, so if you have a `babel.config.js` living in a Hugo Module (and not in the project itself), we recommend using `require` to load the presets/plugins, e.g.:
+
+```js
+module.exports = {
+ presets: [
+ [
+ require("@babel/preset-env"),
+ {
+ useBuiltIns: "entry",
+ corejs: 3,
+ },
+ ],
+ ],
+};
+```
+
+## Options
+
+config
+: (`string`) Path to the Babel configuration file. Hugo will, by default, look for a `babel.config.js` in your project. More information on these configuration files can be found here: [babel configuration](https://babeljs.io/docs/en/configuration).
+
+minified
+: (`bool`) Save as many bytes as possible when printing
+
+noComments
+: (`bool`) Write comments to generated output (true by default)
+
+compact
+: (`bool`) Do not include superfluous whitespace characters and line terminators. Defaults to `auto` if not set.
+
+verbose
+: (`bool`) Log everything
+
+sourceMap
+: (`string`) Output `inline` or `external` sourcemap from the babel compile. External sourcemaps will be written to the target with the output file name + ".map". Input sourcemaps can be read from js.Build and node modules and combined into the output sourcemaps.
diff --git a/content/en/functions/resources/ByType.md b/content/en/functions/resources/ByType.md
new file mode 100644
index 000000000..a5df3befb
--- /dev/null
+++ b/content/en/functions/resources/ByType.md
@@ -0,0 +1,34 @@
+---
+title: resources.ByType
+description: Returns a collection of global resources of the given media type, or nil if none found.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/resources/Get
+ - functions/resources/GetMatch
+ - functions/resources/GetRemote
+ - functions/resources/Match
+ - methods/page/Resources
+ returnType: resource.Resources
+ signatures: [resources.ByType MEDIATYPE]
+---
+
+The [media type] is typically one of `image`, `text`, `audio`, `video`, or `application`.
+
+```go-html-template
+{{ range resources.ByType "image" }}
+ <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
+{{ end }}
+```
+
+{{% note %}}
+This function operates on global resources. A global resource is a file within the assets directory, or within any directory mounted to the assets directory.
+
+For page resources, use the [`Resources.ByType`] method on the Page object.
+
+[`Resources.ByType`]: /methods/page/resources
+{{% /note %}}
+
+[media type]: https://en.wikipedia.org/wiki/Media_type
diff --git a/content/en/functions/resources/Concat.md b/content/en/functions/resources/Concat.md
new file mode 100644
index 000000000..3bdf975bf
--- /dev/null
+++ b/content/en/functions/resources/Concat.md
@@ -0,0 +1,21 @@
+---
+title: resources.Concat
+description: Concatenates a slice of resources.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related: []
+ returnType: resource.Resource
+ signatures: ['resources.Concat TARGETPATH [RESOURCE...]']
+---
+
+```go-html-template
+{{ $plugins := resources.Get "js/plugins.js" }}
+{{ $global := resources.Get "js/global.js" }}
+{{ $js := slice $plugins $global | resources.Concat "js/bundle.js" }}
+```
+
+Asset files of the same [media type] can be bundled into one resource using the `resources.Concat` function which takes two arguments, the target path for the created resource bundle and a slice of resource objects to be concatenated.
+
+[media type]: https://en.wikipedia.org/wiki/Media_type
diff --git a/content/en/functions/resources/Copy.md b/content/en/functions/resources/Copy.md
new file mode 100644
index 000000000..f8e962aee
--- /dev/null
+++ b/content/en/functions/resources/Copy.md
@@ -0,0 +1,32 @@
+---
+title: resources.Copy
+description: Copies the given resource to the target path.
+categories: []
+action:
+ aliases: []
+ related: []
+ returnType: resource.Resource
+ signatures: [resources.Copy TARGETPATH RESOURCE]
+---
+
+{{< new-in 0.100.0 >}}
+
+```go-html-template
+{{ with resources.Get "images/a.jpg" }}
+ {{ with resources.Copy "img/new-image-name.jpg" . }}
+ <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
+ {{ end }}
+{{ end }}
+```
+
+The relative URL of the new published resource will be:
+
+```text
+/img/new-image-name.jpg
+```
+
+The target path must be different than the source path, as shown in the example above.
+
+{{% note %}}
+Use the `resources.Copy` function with global, page, and remote resources.
+{{% /note %}}
diff --git a/content/en/functions/resources/ExecuteAsTemplate.md b/content/en/functions/resources/ExecuteAsTemplate.md
new file mode 100644
index 000000000..d17f0580c
--- /dev/null
+++ b/content/en/functions/resources/ExecuteAsTemplate.md
@@ -0,0 +1,56 @@
+---
+title: resources.ExecuteAsTemplate
+description: Creates a resource from a Go template, parsed and executed with the given context.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/resources/FromString
+ returnType: resource.Resource
+ signatures: [resources.ExecuteAsTemplate TARGETPATH CONTEXT RESOURCE]
+---
+
+Hugo publishes the resource to the target path when you call its`.Publish`, `.Permalink`, or `.RelPermalink` method. The resource is cached, using the target path as the cache key.
+
+Let's say you have a CSS file that you wish to populate with values from your site configuration:
+
+{{< code file=assets/css/template.css lang=go-html-template >}}
+body {
+ background-color: {{ site.Params.style.bg_color }};
+ color: {{ site.Params.style.text_color }};
+}
+{{< /code >}}
+
+And your site configuration contains:
+
+{{< code-toggle file=hugo >}}
+[params.style]
+bg_color = '#fefefe'
+text_color = '#222'
+{{< /code-toggle >}}
+
+Place this in your baseof.html template:
+
+```go-html-template
+{{ with resources.Get "css/template.css" }}
+ {{ with resources.ExecuteAsTemplate "css/main.css" $ . }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+ {{ end }}
+{{ end }}
+```
+
+The example above:
+
+1. Captures the template as a resource
+2. Executes the resource as a template, passing the current page in context
+3. Publishes the resource to css/main.css
+
+The result is:
+
+{{< code file=public/css/main.css >}}
+body {
+ background-color: #fefefe;
+ color: #222;
+}
+{{< /code >}}
diff --git a/content/en/functions/resources/Fingerprint.md b/content/en/functions/resources/Fingerprint.md
new file mode 100644
index 000000000..685214f96
--- /dev/null
+++ b/content/en/functions/resources/Fingerprint.md
@@ -0,0 +1,42 @@
+---
+title: resources.Fingerprint
+description: Cryptographically hashes the content of the given resource.
+categories: []
+keywords: []
+action:
+ aliases: [fingerprint]
+ related:
+ - functions/js/Build
+ - functions/resources/Babel
+ - functions/resources/Minify
+ - functions/resources/PostCSS
+ - functions/resources/PostProcess
+ - functions/resources/ToCSS
+ returnType: resource.Resource
+ signatures: ['resources.Fingerprint [ALGORITHM] RESOURCE']
+---
+
+```go-html-template
+{{ with resources.Get "js/main.js" }}
+ {{ with . | fingerprint "sha256" }}
+ <script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script>
+ {{ end }}
+{{ end }}
+```
+
+Hugo renders this to something like:
+
+```html
+<script src="/js/main.62e...df1.js" integrity="sha256-Yuh...rfE=" crossorigin="anonymous"></script>
+```
+
+Although most commonly used with CSS and JavaScript resources, you can use the `resources.Fingerprint` function with any resource type.
+
+The hash algorithm may be one of `md5`, `sha256` (default), `sha384`, or `sha512`.
+
+After cryptographically hashing the resource content:
+
+1. The values returned by the `.Permalink` and `.RelPermalink` methods include the hash sum
+2. The resource's `.Data.Integrity` method returns a [Subresource Integrity] (SRI) value consisting of the name of the hash algorithm, one hyphen, and the base64-encoded hash sum
+
+[Subresource Integrity]: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
diff --git a/content/en/functions/resources/FromString.md b/content/en/functions/resources/FromString.md
new file mode 100644
index 000000000..6c22b5310
--- /dev/null
+++ b/content/en/functions/resources/FromString.md
@@ -0,0 +1,71 @@
+---
+title: resources.FromString
+description: Creates a resource from a string.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/resources/ExecuteAsTemplate
+ returnType: resource.Resource
+ signatures: [resources.FromString TARGETPATH STRING]
+---
+
+Hugo publishes the resource to the target path when you call its`.Publish`, `.Permalink`, or `.RelPermalink` method. The resource is cached, using the target path as the cache key.
+
+Let's say you need to publish a file named "site.json" in the root of your public directory, containing the build date, the Hugo version used to build the site, and the date that the content was last modified. For example:
+
+```json
+{
+ "build_date": "2023-10-03T10:50:40-07:00",
+ "hugo_version": "0.120.0",
+ "last_modified": "2023-10-02T15:21:27-07:00"
+}
+```
+
+Place this in your baseof.html template:
+
+```go-html-template
+{{ if .IsHome }}
+ {{ $rfc3339 := "2006-01-02T15:04:05Z07:00" }}
+ {{ $m := dict
+ "hugo_version" hugo.Version
+ "build_date" (now.Format $rfc3339)
+ "last_modified" (site.LastChange.Format $rfc3339)
+ }}
+ {{ $json := jsonify $m }}
+ {{ $r := resources.FromString "site.json" $json }}
+ {{ $r.Publish }}
+{{ end }}
+```
+
+The example above:
+
+1. Creates a map with the relevant key/value pairs using the [`dict`] function
+2. Encodes the map as a JSON string using the [`jsonify`] function
+3. Creates a resource from the JSON string using the `resources.FromString` function
+4. Publishes the file to the root of the public directory using the resource's `.Publish` method
+
+Combine `resources.FromString` with [`resources.ExecuteAsTemplate`] if your string contains template actions. Rewriting the example above:
+
+```go-html-template
+{{ if .IsHome }}
+ {{ $string := `
+ {{ $rfc3339 := "2006-01-02T15:04:05Z07:00" }}
+ {{ $m := dict
+ "hugo_version" hugo.Version
+ "build_date" (now.Format $rfc3339)
+ "last_modified" (site.LastChange.Format $rfc3339)
+ }}
+ {{ $json := jsonify $m }}
+ `
+ }}
+ {{ $r := resources.FromString "" $string }}
+ {{ $r = $r | resources.ExecuteAsTemplate "site.json" . }}
+ {{ $r.Publish }}
+{{ end }}
+```
+
+[`dict`]: /functions/collections/dictionary
+[`jsonify`]: /functions/encoding/jsonify
+[`resources.ExecuteAsTemplate`]: /functions/resources/executeastemplate
diff --git a/content/en/functions/resources/Get.md b/content/en/functions/resources/Get.md
new file mode 100644
index 000000000..a8b75d52b
--- /dev/null
+++ b/content/en/functions/resources/Get.md
@@ -0,0 +1,30 @@
+---
+title: resources.Get
+description: Returns a global resource from the given path, or nil if none found.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/resources/ByType
+ - functions/resources/GetMatch
+ - functions/resources/GetRemote
+ - functions/resources/Match
+ - methods/page/Resources
+ returnType: resource.Resource
+ signatures: [resources.Get PATH]
+---
+
+```go-html-template
+{{ with resources.Get "images/a.jpg" }}
+ <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
+{{ end }}
+```
+
+{{% note %}}
+This function operates on global resources. A global resource is a file within the assets directory, or within any directory mounted to the assets directory.
+
+For page resources, use the [`Resources.Get`] method on the Page object.
+
+[`Resources.Get`]: /methods/page/resources
+{{% /note %}}
diff --git a/content/en/functions/resources/GetMatch.md b/content/en/functions/resources/GetMatch.md
new file mode 100644
index 000000000..fde26c09d
--- /dev/null
+++ b/content/en/functions/resources/GetMatch.md
@@ -0,0 +1,36 @@
+---
+title: resources.GetMatch
+description: Returns the first global resource from paths matching the given glob pattern, or nil if none found.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/resources/ByType
+ - functions/resources/Get
+ - functions/resources/GetRemote
+ - functions/resources/Match
+ - methods/page/Resources
+ returnType: resource.Resource
+ signatures: [resources.GetMatch PATTERN]
+---
+
+```go-html-template
+{{ with resources.GetMatch "images/*.jpg" }}
+ <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
+{{ end }}
+```
+
+{{% note %}}
+This function operates on global resources. A global resource is a file within the assets directory, or within any directory mounted to the assets directory.
+
+For page resources, use the [`Resources.GetMatch`] method on the Page object.
+
+[`Resources.GetMatch`]: /methods/page/resources
+{{% /note %}}
+
+Hugo determines a match using a case-insensitive [glob pattern].
+
+{{% include "functions/_common/glob-patterns.md" %}}
+
+[glob pattern]: https://github.com/gobwas/glob#example
diff --git a/content/en/functions/resources/GetRemote.md b/content/en/functions/resources/GetRemote.md
new file mode 100644
index 000000000..0e6b91b64
--- /dev/null
+++ b/content/en/functions/resources/GetRemote.md
@@ -0,0 +1,177 @@
+---
+title: resources.GetRemote
+description: Returns a remote resource from the given URL, or nil if none found.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/data/GetCSV
+ - functions/data/GetJSON
+ - functions/resources/ByType
+ - functions/resources/Get
+ - functions/resources/GetMatch
+ - functions/resources/Match
+ - methods/page/Resources
+ returnType: resource.Resource
+ signatures: ['resources.GetRemote URL [OPTIONS]']
+toc: true
+---
+
+```go-html-template
+{{ $url := "https://example.org/images/a.jpg" }}
+{{ with resources.GetRemote $url }}
+ {{ with .Err }}
+ {{ errorf "%s" . }}
+ {{ else }}
+ <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get remote resource %q" $url }}
+{{ end }}
+```
+
+## Options
+
+The `resources.GetRemote` function takes an optional map of options.
+
+```go-html-template
+{{ $url := "https://example.org/api" }}
+{{ $opts := dict
+ "headers" (dict "Authorization" "Bearer abcd")
+}}
+{{ $resource := resources.GetRemote $url $opts }}
+```
+
+If you need multiple values for the same header key, use a slice:
+
+```go-html-template
+{{ $url := "https://example.org/api" }}
+{{ $opts := dict
+ "headers" (dict "X-List" (slice "a" "b" "c"))
+}}
+{{ $resource := resources.GetRemote $url $opts }}
+```
+
+You can also change the request method and set the request body:
+
+```go-html-template
+{{ $url := "https://example.org/api" }}
+{{ $opts := dict
+ "method" "post"
+ "body" `{"complete": true}`
+ "headers" (dict "Content-Type" "application/json")
+}}
+{{ $resource := resources.GetRemote $url $opts }}
+```
+
+## Remote data
+
+When retrieving remote data, use the [`transform.Unmarshal`] function to [unmarshal] the response.
+
+[`transform.Unmarshal`]: /functions/transform/unmarshal
+[unmarshal]: /getting-started/glossary/#unmarshal
+
+```go-html-template
+{{ $data := "" }}
+{{ $url := "https://example.org/books.json" }}
+{{ with resources.GetRemote $url }}
+ {{ with .Err }}
+ {{ errorf "%s" . }}
+ {{ else }}
+ {{ $data = . | transform.Unmarshal }}
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get remote resource %q" $url }}
+{{ end }}
+```
+
+## Error handling
+
+The [`Err`] method on a resource returned by the `resources.GetRemote` function returns an error message if the HTTP request fails, else nil. If you do not handle the error yourself, Hugo will fail the build.
+
+[`Err`]: /methods/resource/err
+
+```go-html-template
+{{ $url := "https://broken-example.org/images/a.jpg" }}
+{{ with resources.GetRemote $url }}
+ {{ with .Err }}
+ {{ errorf "%s" . }}
+ {{ else }}
+ <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get remote resource %q" $url }}
+{{ end }}
+```
+
+To log an error as a warning instead of an error:
+
+```go-html-template
+{{ $url := "https://broken-example.org/images/a.jpg" }}
+{{ with resources.GetRemote $url }}
+ {{ with .Err }}
+ {{ warnf "%s" . }}
+ {{ else }}
+ <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get remote resource %q" $url }}
+{{ end }}
+```
+
+## HTTP response
+
+The [`Data`] method on a resource returned by the `resources.GetRemote` function returns information from the HTTP response.
+
+[`Data`]: /methods/resource/data
+
+```go-html-template
+{{ $url := "https://example.org/images/a.jpg" }}
+{{ with resources.GetRemote $url }}
+ {{ with .Err }}
+ {{ errorf "%s" . }}
+ {{ else }}
+ {{ with .Data }}
+ {{ .ContentLength }} → 42764
+ {{ .ContentType }} → image/jpeg
+ {{ .Status }} → 200 OK
+ {{ .StatusCode }} → 200
+ {{ .TransferEncoding }} → []
+ {{ end }}
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get remote resource %q" $url }}
+{{ end }}
+```
+
+ContentLength
+: (`int`) The content length in bytes.
+
+ContentType
+: (`string`) The content type.
+
+Status
+: (`string`) The HTTP status text.
+
+StatusCode
+: (`int`) The HTTP status code.
+
+TransferEncoding
+: (`string`) The transfer encoding.
+
+## Caching
+
+Resources returned from `resources.GetRemote` are cached to disk. See [configure file caches] for details.
+
+By default, Hugo derives the cache key from the arguments passed to the function, the URL and the options map, if any.
+
+Override the cache key by setting a `key` in the options map. Use this approach to have more control over how often Hugo fetches a remote resource.
+
+```go-html-template
+{{ $url := "https://example.org/images/a.jpg" }}
+{{ $cacheKey := print $url (now.Format "2006-01-02") }}
+{{ $resource := resource.GetRemote $url (dict "key" $cacheKey) }}
+```
+
+[configure file caches]: /getting-started/configuration/#configure-file-caches
diff --git a/content/en/functions/resources/Match.md b/content/en/functions/resources/Match.md
new file mode 100644
index 000000000..0044351f1
--- /dev/null
+++ b/content/en/functions/resources/Match.md
@@ -0,0 +1,36 @@
+---
+title: resources.Match
+description: Returns a collection of global resources from paths matching the given glob pattern, or nil if none found.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/resources/ByType
+ - functions/resources/Get
+ - functions/resources/GetMatch
+ - functions/resources/GetRemote
+ - methods/page/Resources
+ returnType: resource.Resources
+ signatures: [resources.Match PATTERN]
+---
+
+```go-html-template
+{{ range resources.Match "images/*.jpg" }}
+ <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt="">
+{{ end }}
+```
+
+{{% note %}}
+This function operates on global resources. A global resource is a file within the assets directory, or within any directory mounted to the assets directory.
+
+For page resources, use the [`Resources.Match`] method on the Page object.
+
+[`Resources.Match`]: /methods/page/resources
+{{% /note %}}
+
+Hugo determines a match using a case-insensitive [glob pattern].
+
+{{% include "functions/_common/glob-patterns.md" %}}
+
+[glob pattern]: https://github.com/gobwas/glob#example
diff --git a/content/en/functions/resources/Minify.md b/content/en/functions/resources/Minify.md
new file mode 100644
index 000000000..44f5f990b
--- /dev/null
+++ b/content/en/functions/resources/Minify.md
@@ -0,0 +1,23 @@
+---
+title: resources.Minify
+description: Minifies the given resource.
+categories: []
+keywords: []
+action:
+ aliases: [minify]
+ related:
+ - functions/js/Build
+ - functions/resources/Babel
+ - functions/resources/Fingerprint
+ - functions/resources/PostCSS
+ - functions/resources/ToCSS
+ returnType: resource.Resource
+ signatures: [resources.Minify RESOURCE]
+---
+
+```go-html-template
+{{ $css := resources.Get "css/main.css" }}
+{{ $style := $css | minify }}
+```
+
+Any CSS, JS, JSON, HTML, SVG or XML resource can be minified using resources.Minify which takes for argument the resource object.
diff --git a/content/en/functions/resources/PostCSS.md b/content/en/functions/resources/PostCSS.md
new file mode 100644
index 000000000..a9f9ed3c8
--- /dev/null
+++ b/content/en/functions/resources/PostCSS.md
@@ -0,0 +1,129 @@
+---
+title: resources.PostCSS
+description: Processes the given resource with PostCSS using any PostCSS plugin.
+categories: []
+keywords: []
+action:
+ aliases: [postCSS]
+ related:
+ - functions/resources/Fingerprint
+ - functions/resources/Minify
+ - functions/resources/PostProcess
+ - functions/resources/ToCSS
+ returnType: resource.Resource
+ signatures: ['resources.PostCSS [OPTIONS] RESOURCE']
+toc: true
+---
+
+```go-html-template
+{{ with resources.Get "css/main.css" | postCSS }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+{{ end }}
+```
+
+## Setup
+
+Follow the steps below to transform CSS using any of the available [PostCSS plugins].
+
+Step 1
+: Install [Node.js].
+
+Step 2
+: Install the required Node.js packages in the root of your project. For example, to add vendor prefixes to your CSS rules:
+
+```sh
+npm i -D postcss postcss-cli autoprefixer
+```
+
+Step 3
+: Create a PostCSS configuration file in the root of your project. You must name this file `postcss.config.js` or another [supported file name]. For example:
+
+```js
+module.exports = {
+ plugins: [
+ require('autoprefixer')
+ ]
+};
+```
+
+{{% note %}}
+{{% include "functions/resources/_common/postcss-windows-warning.md" %}}
+{{% /note %}}
+
+Step 4
+: Place your CSS file within the `assets/css` directory.
+
+Step 5
+: Process the resource with PostCSS:
+
+```go-html-template
+{{ with resources.Get "css/main.css" | postCSS }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+{{ end }}
+```
+
+## Options
+
+The `resources.PostCSS` method takes an optional map of options.
+
+config
+: (`string`) The directory that contains the PostCSS configuration file. Default is the root of the project directory.
+
+noMap
+: (`bool`) Default is `false`. If `true`, disables inline sourcemaps.
+
+inlineImports
+: (`bool`) Default is `false`. Enable inlining of @import statements. It does so recursively, but will only import a file once. URL imports (e.g. `@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');`) and imports with media queries will be ignored. Note that this import routine does not care about the CSS spec, so you can have @import anywhere in the file. Hugo will look for imports relative to the module mount and will respect theme overrides.
+
+skipInlineImportsNotFound
+: (`bool`) Default is `false`. Before Hugo 0.99.0 when `inlineImports` was enabled and we failed to resolve an import, we logged it as a warning. We now fail the build. If you have regular CSS imports in your CSS that you want to preserve, you can either use imports with URL or media queries (Hugo does not try to resolve those) or set `skipInlineImportsNotFound` to true.
+
+```go-html-template
+{{ $opts := dict "config" "config-directory" "noMap" true }}
+{{ with resources.Get "css/main.css" | postCSS $opts }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+{{ end }}
+```
+
+## No configuration file
+
+To avoid using a PostCSS configuration file, you can specify a minimal configuration using the options map.
+
+use
+: (`string`) A space-delimited list of PostCSS plugins to use.
+
+parser
+: (`string`) A custom PostCSS parser.
+
+stringifier
+: (`string`) A custom PostCSS stringifier.
+
+syntax
+: (`string`) Custom postcss syntax.
+
+```go-html-template
+{{ $opts := dict "use" "autoprefixer postcss-color-alpha" }}
+{{ with resources.Get "css/main.css" | postCSS $opts }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+{{ end }}
+```
+
+## Check environment
+
+The current Hugo environment name (set by `--environment` or in configuration or OS environment) is available in the Node context, which allows constructs like this:
+
+```js
+const autoprefixer = require('autoprefixer');
+const purgecss = require('@fullhuman/postcss-purgecss');
+module.exports = {
+ plugins: [
+ autoprefixer,
+ process.env.HUGO_ENVIRONMENT !== 'development' ? purgecss : null
+ ]
+}
+```
+
+[node.js]: https://nodejs.org/en/download
+[postcss plugins]: https://www.postcss.parts/
+[supported file name]: https://github.com/postcss/postcss-load-config#usage
+[transpile to CSS]: /functions/resources/tocss.md
diff --git a/content/en/functions/resources/PostProcess.md b/content/en/functions/resources/PostProcess.md
new file mode 100644
index 000000000..f765ea9af
--- /dev/null
+++ b/content/en/functions/resources/PostProcess.md
@@ -0,0 +1,160 @@
+---
+title: resources.PostProcess
+description: Processes the given resource after the build.
+categories: []
+keywords: []
+action:
+ aliases: []
+ related:
+ - functions/resources/Fingerprint
+ - functions/resources/Minify
+ - functions/resources/PostCSS
+ - functions/resources/ToCSS
+ returnType: postpub.PostPublishedResource
+ signatures: [resources.PostProcess RESOURCE]
+toc: true
+---
+
+```go-html-template
+{{ with resources.Get "css/main.css" }}
+ {{ if hugo.IsDevelopment }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+ {{ else }}
+ {{ with . | postCSS | minify | fingerprint | resources.PostProcess }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
+ {{ end }}
+ {{ end }}
+{{ end }}
+```
+
+Marking a resource with `resources.PostProcess` postpones transformations until the build has finished.
+
+Call `resources.PostProcess` when one or more of the steps in the transformation chain depends on the result of the build.
+
+A prime use case for this is purging unused CSS rules using the [PurgeCSS] plugin for the PostCSS Node.js package.
+
+## CSS Purging
+
+{{% note %}}
+There are several ways to set up CSS purging with PostCSS in Hugo. If you have a simple project, you should consider going the simpler route and drop the use of `resources.PostProcess` and just extract keywords from the templates. See the [Tailwind documentation](https://tailwindcss.com/docs/controlling-file-size/#app) for examples.
+{{% /note %}}
+
+Step 1
+: Install [Node.js].
+
+Step 2
+: Install the required Node.js packages in the root of your project:
+
+```sh
+npm i -D postcss postcss-cli autoprefixer @fullhuman/postcss-purgecss
+```
+
+Step 3
+: Create a PostCSS configuration file in the root of your project. You must name this file `postcss.config.js` or another [supported file name]. For example:
+
+```js
+const autoprefixer = require('autoprefixer');
+const purgecss = require('@fullhuman/postcss-purgecss')({
+ content: ['./hugo_stats.json'],
+ defaultExtractor: content => {
+ const els = JSON.parse(content).htmlElements;
+ return [
+ ...(els.tags || []),
+ ...(els.classes || []),
+ ...(els.ids || []),
+ ];
+ },
+ // https://purgecss.com/safelisting.html
+ safelist: []
+});
+
+module.exports = {
+ plugins: [
+ autoprefixer,
+ process.env.HUGO_ENVIRONMENT !== 'development' ? purgecss : null
+ ]
+};
+```
+
+{{% note %}}
+{{% include "functions/resources/_common/postcss-windows-warning.md" %}}
+{{% /note %}}
+
+Step 4
+: Enable creation of the `hugo_stats.json` file when building the site. If you are only using this for the production build, consider placing it below [config/production].
+
+{{< code-toggle file=hugo >}}
+[build.buildStats]
+enable = true
+{{< /code-toggle >}}
+
+See the [configure build] documentation for details and options.
+
+Step 5
+: Place your CSS file within the `assets/css` directory.
+
+Step 6
+: If the current environment is not `development`, process the resource with PostCSS:
+
+```go-html-template
+{{ with resources.Get "css/main.css" }}
+ {{ if hugo.IsDevelopment }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+ {{ else }}
+ {{ with . | postCSS | minify | fingerprint | resources.PostProcess }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
+ {{ end }}
+ {{ end }}
+{{ end }}
+```
+
+## Environment variables
+
+Hugo passes these environment variables to PostCSS, which allows you to do something like:
+
+```js
+process.env.HUGO_ENVIRONMENT === 'production' ? [autoprefixer] : []
+```
+
+PWD
+: The absolute path to the project working directory.
+
+HUGO_ENVIRONMENT
+: The current Hugo environment, set with the `--environment` command line flag.
+Default is `production` for `hugo` and `development` for `hugo server`.
+
+HUGO_PUBLISHDIR
+: The absolute path to the publish directory (the `public` directory). Note that the value will always point to a directory on disk even when running `hugo server` in memory mode. If you write to this folder from PostCSS when running the server, you could run the server with one of these flags:
+
+```sh
+hugo server --renderToDisk
+hugo server --renderStaticToDisk
+```
+
+Also, Hugo will add environment variables for all files mounted below `assets/_jsconfig`. A default mount will be set up with files in the project root matching this regexp: `(babel|postcss|tailwind)\.config\.js`.
+
+These will get environment variables named on the form `HUGO_FILE_:filename:` where `:filename:` is all upper case with periods replaced with underscore. This allows you to do something like:
+
+```js
+let tailwindConfig = process.env.HUGO_FILE_TAILWIND_CONFIG_JS || './tailwind.config.js';
+```
+
+## Limitations
+
+Do not use `resources.PostProcess` when running Hugo's built-in development server. The examples above specifically prevent this by verifying that the current environment is not "development".
+
+The `resources.PostProcess` function only works within templates that produce HTML files.
+
+You cannot manipulate the values returned from the resource’s methods. For example, the `strings.ToUpper` function in this example will not work as expected:
+
+```go-html-template
+{{ $css := resources.Get "css/main.css" }}
+{{ $css = $css | resources.PostCSS | minify | fingerprint | resources.PostProcess }}
+{{ $css.RelPermalink | strings.ToUpper }}
+```
+
+[node.js]: https://nodejs.org/en/download
+[supported file name]: https://github.com/postcss/postcss-load-config#usage
+[config/production]: /getting-started/configuration/#configuration-directory
+[configure build]: /getting-started/configuration/#configure-build
+[purgecss]: https://github.com/FullHuman/purgecss#readme
diff --git a/content/en/functions/resources/ToCSS.md b/content/en/functions/resources/ToCSS.md
new file mode 100644
index 000000000..872bf996b
--- /dev/null
+++ b/content/en/functions/resources/ToCSS.md
@@ -0,0 +1,224 @@
+---
+title: resources.ToCSS
+description: Transpiles Sass to CSS.
+categories: []
+keywords: []
+action:
+ aliases: [toCSS]
+ related:
+ - functions/resources/Fingerprint
+ - functions/resources/Minify
+ - functions/resources/PostCSS
+ - functions/resources/PostProcess
+ returnType: resource.Resource
+ signatures: ['resources.ToCSS [OPTIONS] RESOURCE']
+toc: true
+---
+
+```go-html-template
+{{ with resources.Get "sass/main.scss" }}
+ {{ $opts := dict "transpiler" "libsass" "targetPath" "css/style.css" }}
+ {{ with . | toCSS $opts }}
+ {{ if hugo.IsDevelopment }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+ {{ else }}
+ {{ with . | minify | fingerprint }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
+ {{ end }}
+ {{ end }}
+ {{ end }}
+{{ end }}
+```
+
+Transpile Sass to CSS using the LibSass transpiler included in Hugo's extended edition, or [install Dart Sass](#dart-sass) to use the latest features of the Sass language.
+
+Sass has two forms of syntax: [SCSS] and [indented]. Hugo supports both.
+
+[scss]: https://sass-lang.com/documentation/syntax#scss
+[indented]: https://sass-lang.com/documentation/syntax#the-indented-syntax
+
+## Options
+
+transpiler
+: (`string`) The transpiler to use, either `libsass` (default) or `dartsass`. Hugo's extended edition includes the LibSass transpiler. To use the Dart Sass transpiler, see the [installation instructions](#dart-sass) below.
+
+targetPath
+: (`string`) If not set, the transformed resource's target path will be the original path of the asset file with its extension replaced by `.css`.
+
+vars
+: (`map`) A map of key/value pairs that will be available in the `hugo:vars` namespace. Useful for [initializing Sass variables from Hugo templates](https://discourse.gohugo.io/t/42053/).
+
+```scss
+// LibSass
+@import "hugo:vars";
+
+// Dart Sass
+@use "hugo:vars" as v;
+```
+
+outputStyle
+: (`string`) Output styles available to LibSass include `nested` (default), `expanded`, `compact`, and `compressed`. Output styles available to Dart Sass include `expanded` (default) and `compressed`.
+
+precision
+: (`int`) Precision of floating point math. Not applicable to Dart Sass.
+
+enableSourceMap
+: (`bool`) If `true`, generates a source map.
+
+sourceMapIncludeSources
+: (`bool`) If `true`, embeds sources in the generated source map. Not applicable to LibSass.
+
+includePaths
+: (`slice`) A slice of paths, relative to the project root, that the transpiler will use when resolving `@use` and `@import` statements.
+
+```go-html-template
+{{ $opts := dict
+ "transpiler" "dartsass"
+ "targetPath" "css/style.css"
+ "vars" site.Params.styles
+ "enableSourceMap" (not hugo.IsProduction)
+ "includePaths" (slice "node_modules/bootstrap/scss")
+}}
+{{ with resources.Get "sass/main.scss" | toCSS $opts | minify | fingerprint }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
+{{ end }}
+```
+
+## Dart Sass
+
+The extended version of Hugo includes [LibSass] to transpile Sass to CSS. In 2020, the Sass team deprecated LibSass in favor of [Dart Sass].
+
+Use the latest features of the Sass language by installing Dart Sass in your development and production environments.
+
+### Installation overview
+
+Dart Sass is compatible with Hugo v0.114.0 and later.
+
+If you have been using Embedded Dart Sass[^1] with Hugo v0.113.0 and earlier, uninstall Embedded Dart Sass, then install Dart Sass. If you have installed both, Hugo will use Dart Sass.
+
+If you install Hugo as a [Snap package] there is no need to install Dart Sass. The Hugo Snap package includes Dart Sass.
+
+[^1]: In 2023, the Sass team deprecated Embedded Dart Sass in favor of Dart Sass.
+
+### Installing in a development environment
+
+When you install Dart Sass somewhere in your PATH, Hugo will find it.
+
+OS|Package manager|Site|Installation
+:--|:--|:--|:--
+Linux|Homebrew|[brew.sh]|`brew install sass/sass/sass`
+Linux|Snap|[snapcraft.io]|`sudo snap install dart-sass`
+macOS|Homebrew|[brew.sh]|`brew install sass/sass/sass`
+Windows|Chocolatey|[chocolatey.org]|`choco install sass`
+Windows|Scoop|[scoop.sh]|`scoop install sass`
+
+You may also install [prebuilt binaries] for Linux, macOS, and Windows.
+
+Run `hugo env` to list the active transpilers.
+
+### Installing in a production environment
+
+For [CI/CD] deployments (e.g., GitHub Pages, GitLab Pages, Netlify, etc.) you must edit the workflow to install Dart Sass before Hugo builds the site[^2]. Some providers allow you to use one of the package managers above, or you can download and extract one of the prebuilt binaries.
+
+[^2]: You do not have to do this if (a) you have not modified the assets cache location, and (b) you have not set `useResourceCacheWhen` to `never` in your [site configuration], and (c) you add and commit your resources directory to your repository.
+
+#### GitHub Pages
+
+To install Dart Sass for your builds on GitHub Pages, add this step to the GitHub Pages workflow file:
+
+```yaml
+- name: Install Dart Sass
+ run: sudo snap install dart-sass
+```
+
+If you are using GitHub Pages for the first time with your repository, GitHub provides a [starter workflow] for Hugo that includes Dart Sass. This is the simplest way to get started.
+
+#### GitLab Pages
+
+To install Dart Sass for your builds on GitLab Pages, the `.gitlab-ci.yml` file should look something like this:
+
+```yaml
+variables:
+ HUGO_VERSION: 0.115.1
+ DART_SASS_VERSION: 1.63.6
+ GIT_DEPTH: 0
+ GIT_STRATEGY: clone
+ GIT_SUBMODULE_STRATEGY: recursive
+ TZ: America/Los_Angeles
+image:
+ name: golang:1.20-buster
+pages:
+ script:
+ # Install Dart Sass
+ - curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
+ - tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz
+ - cp -r dart-sass/* /usr/local/bin
+ - rm -rf dart-sass*
+ # Install Hugo
+ - curl -LJO https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb
+ - apt install -y ./hugo_extended_${HUGO_VERSION}_linux-amd64.deb
+ - rm hugo_extended_${HUGO_VERSION}_linux-amd64.deb
+ # Build
+ - hugo --gc --minify
+ artifacts:
+ paths:
+ - public
+ rules:
+ - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+```
+
+#### Netlify
+
+To install Dart Sass for your builds on Netlify, the `netlify.toml` file should look something like this:
+
+```toml
+[build.environment]
+HUGO_VERSION = "0.115.1"
+DART_SASS_VERSION = "1.63.6"
+TZ = "America/Los_Angeles"
+
+[build]
+publish = "public"
+command = """\
+ curl -LJO https://github.com/sass/dart-sass/releases/download/${DART_SASS_VERSION}/dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
+ tar -xf dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
+ rm dart-sass-${DART_SASS_VERSION}-linux-x64.tar.gz && \
+ export PATH=/opt/build/repo/dart-sass:$PATH && \
+ hugo --gc --minify \
+ """
+```
+
+### Example
+
+To transpile with Dart Sass, set `transpiler` to `dartsass` in the options map passed to `resources.ToCSS`. For example:
+
+```go-html-template
+{{ with resources.Get "sass/main.scss" }}
+ {{ $opts := dict "transpiler" "dartsass" "targetPath" "css/style.css" }}
+ {{ with . | toCSS $opts }}
+ {{ if hugo.IsDevelopment }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}">
+ {{ else }}
+ {{ with . | minify | fingerprint }}
+ <link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
+ {{ end }}
+ {{ end }}
+ {{ end }}
+{{ end }}
+```
+
+### Miscellaneous
+
+If you build Hugo from source and run `mage test -v`, the test will fail if you install Dart Sass as a Snap package. This is due to the Snap package's strict confinement model.
+
+[brew.sh]: https://brew.sh/
+[chocolatey.org]: https://community.chocolatey.org/packages/sass
+[ci/cd]: https://en.wikipedia.org/wiki/CI/CD
+[dart sass]: https://sass-lang.com/dart-sass
+[libsass]: https://sass-lang.com/libsass
+[prebuilt binaries]: https://github.com/sass/dart-sass/releases/latest
+[scoop.sh]: https://scoop.sh/#/apps?q=sass
+[site configuration]: /getting-started/configuration/#configure-build
+[snap package]: /installation/linux/#snap
+[snapcraft.io]: https://snapcraft.io/dart-sass
+[starter workflow]: https://github.com/actions/starter-workflows/blob/main/pages/hugo.yml
diff --git a/content/en/functions/resources/_common/_index.md b/content/en/functions/resources/_common/_index.md
new file mode 100644
index 000000000..b57b688b3
--- /dev/null
+++ b/content/en/functions/resources/_common/_index.md
@@ -0,0 +1,12 @@
+---
+_build:
+ list: never
+ publishResources: false
+ render: never
+---
+
+<!--
+Files within this headless branch bundle are markdown snippets. Each file must contain front matter delimiters, though front matter fields are not required.
+
+Include the rendered content using the "include" shortcode.
+-->
diff --git a/content/en/functions/resources/_common/postcss-windows-warning.md b/content/en/functions/resources/_common/postcss-windows-warning.md
new file mode 100644
index 000000000..1b72e74db
--- /dev/null
+++ b/content/en/functions/resources/_common/postcss-windows-warning.md
@@ -0,0 +1,8 @@
+---
+# Do not remove front matter.
+---
+
+If you are a Windows user, and the path to your project contains a space, you must place the PostCSS configuration within the package.json file. See [this example] and issue [#7333].
+
+[this example]: https://github.com/postcss/postcss-load-config#packagejson
+[#7333]: https://github.com/gohugoio/hugo/issues/7333
diff --git a/content/en/functions/resources/_index.md b/content/en/functions/resources/_index.md
new file mode 100644
index 000000000..364b9448d
--- /dev/null
+++ b/content/en/functions/resources/_index.md
@@ -0,0 +1,12 @@
+---
+title: Resource functions
+linkTitle: resources
+description: Template functions to work with resources.
+categories: []
+keywords: []
+menu:
+ docs:
+ parent: functions
+---
+
+Use these functions to work with resources.