diff options
Diffstat (limited to 'docs/content/en/hugo-pipes')
-rwxr-xr-x | docs/content/en/hugo-pipes/_index.md | 15 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/babel.md | 79 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/bundling.md | 24 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/fingerprint.md | 29 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/introduction.md | 143 | ||||
-rw-r--r-- | docs/content/en/hugo-pipes/js.md | 171 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/minification.md | 27 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/postcss.md | 84 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/postprocess.md | 70 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/resource-from-string.md | 31 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/resource-from-template.md | 38 | ||||
-rwxr-xr-x | docs/content/en/hugo-pipes/scss-sass.md | 54 |
12 files changed, 765 insertions, 0 deletions
diff --git a/docs/content/en/hugo-pipes/_index.md b/docs/content/en/hugo-pipes/_index.md new file mode 100755 index 000000000..47411072a --- /dev/null +++ b/docs/content/en/hugo-pipes/_index.md @@ -0,0 +1,15 @@ +--- +title: Hugo Pipes Overview +date: 2018-07-14 +publishdate: 2018-07-14 +lastmod: 2018-07-14 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 10 +weight: 10 +sections_weight: 10 +draft: false +---
\ No newline at end of file diff --git a/docs/content/en/hugo-pipes/babel.md b/docs/content/en/hugo-pipes/babel.md new file mode 100755 index 000000000..76a1d441d --- /dev/null +++ b/docs/content/en/hugo-pipes/babel.md @@ -0,0 +1,79 @@ +--- +title: Babel +description: Hugo Pipes can process JS files with Babel. +date: 2019-03-21 +publishdate: 2019-03-21 +lastmod: 2019-03-21 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 48 +weight: 48 +sections_weight: 48 +draft: false +--- + +Any JavaScript resource file can be transpiled to another JavaScript version using `resources.Babel` which takes for argument the resource object and an optional dict of options listed below. Babel uses the [babel cli](https://babeljs.io/docs/en/babel-cli). + + +{{% note %}} +Hugo Pipe's Babel requires the `@babel/cli` and `@babel/core` JavaScript packages to be installed in the project or globally (`npm install -g @babel/cli @babel/core`) along with any Babel plugin(s) or preset(s) used (e.g., `npm install @babel/preset-env --save-dev`). + +If you are using the Hugo Snap package, Babel and plugin(s) need to be installed locally within your Hugo site directory, e.g., `npm install @babel/cli @babel/core --save-dev` without the `-g` flag. +{{% /note %}} + + +### Config + +{{< new-in "v0.75.0" >}} + +In Hugo `v0.75` we improved the way we resolve JS configuration and dependencies. One of them is that we now 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 much 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 + +### Examples + +```go-html-template +{{- $transpiled := resources.Get "scripts/main.js" | babel -}} +``` + +Or with options: + +```go-html-template +{{ $opts := dict "noComments" true }} +{{- $transpiled := resources.Get "scripts/main.js" | babel $opts -}} +``` diff --git a/docs/content/en/hugo-pipes/bundling.md b/docs/content/en/hugo-pipes/bundling.md new file mode 100755 index 000000000..79b866c93 --- /dev/null +++ b/docs/content/en/hugo-pipes/bundling.md @@ -0,0 +1,24 @@ +--- +title: Asset bundling +description: Hugo Pipes can bundle any number of assets together. +date: 2018-07-14 +publishdate: 2018-07-14 +lastmod: 2018-07-14 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 60 +weight: 60 +sections_weight: 60 +draft: false +--- + +Asset files of the same MIME type can be bundled into one resource using `resources.Concat` which takes two arguments, a target path and a slice of resource objects. + +```go-html-template +{{ $plugins := resources.Get "js/plugins.js" }} +{{ $global := resources.Get "js/global.js" }} +{{ $js := slice $plugins $global | resources.Concat "js/bundle.js" }} +``` diff --git a/docs/content/en/hugo-pipes/fingerprint.md b/docs/content/en/hugo-pipes/fingerprint.md new file mode 100755 index 000000000..b58b577db --- /dev/null +++ b/docs/content/en/hugo-pipes/fingerprint.md @@ -0,0 +1,29 @@ +--- +title: Fingerprinting and SRI +description: Hugo Pipes allows Fingerprinting and Subresource Integrity. +date: 2018-07-14 +publishdate: 2018-07-14 +lastmod: 2018-07-14 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 70 +weight: 70 +sections_weight: 70 +draft: false +--- + + +Fingerprinting and [SRI](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity) can be applied to any asset file using `resources.Fingerprint` which takes two arguments, the resource object and a [hash function](https://en.wikipedia.org/wiki/Cryptographic_hash_function). + +The default hash function is `sha256`. Other available functions are `sha384` (from Hugo `0.55`), `sha512` and `md5`. + +Any so processed asset will bear a `.Data.Integrity` property containing an integrity string, which is made up of the name of the hash function, one hyphen and the base64-encoded hash sum. + +```go-html-template +{{ $js := resources.Get "js/global.js" }} +{{ $secureJS := $js | resources.Fingerprint "sha512" }} +<script type="text/javascript" src="{{ $secureJS.Permalink }}" integrity="{{ $secureJS.Data.Integrity }}"></script> +``` diff --git a/docs/content/en/hugo-pipes/introduction.md b/docs/content/en/hugo-pipes/introduction.md new file mode 100755 index 000000000..83d64d1d3 --- /dev/null +++ b/docs/content/en/hugo-pipes/introduction.md @@ -0,0 +1,143 @@ +--- +title: Hugo Pipes Introduction +linkTitle: Hugo Pipes +description: Hugo Pipes is Hugo's asset processing set of functions. +date: 2018-07-14 +publishdate: 2018-07-14 +lastmod: 2018-07-14 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 20 +weight: 01 +sections_weight: 01 +draft: false +toc: true +aliases: [/assets/] +--- + +## Find Resources in /assets + +This is about the global Resources mounted inside `/assets`. For the `.Page` scoped Resources, see [Page Resources](/content-management/page-resources/). + +Note that you can mount any directory into Hugo's virtual `assets` folder using the [Mount Configuration](/hugo-modules/configuration/#module-config-mounts). + +| Function | Description | +| ------------- | ------------- | +| `resources.Get` | Get locates the filename given in Hugo's assets filesystem and creates a `Resource` object that can be used for further transformations. See [Get Resource with resources.Get and resources.GetRemote](#get-resource-with-resourcesget-and-resourcesgetremote). | +| `resources.GetRemote` | Same as `Get`, but it accepts remote URLs. See [Get Resource with resources.Get and resources.GetRemote](#get-resource-with-resourcesget-and-resourcesgetremote).| +| `resources.GetMatch` | `GetMatch` finds the first Resource matching the given pattern, or nil if none found. See Match for a more complete explanation about the rules used. | +| `resources.Match` | `Match` gets all resources matching the given base path prefix, e.g "*.png" will match all png files. The "*" does not match path delimiters (/), so if you organize your resources in sub-folders, you need to be explicit about it, e.g.: "images/*.png". To match any PNG image anywhere in the bundle you can do "\*\*.png", and to match all PNG images below the images folder, use "images/\*\*.jpg". The matching is case insensitive. Match matches by using the files name with path relative to the file system root with Unix style slashes (/) and no leading slash, e.g. "images/logo.png". See https://github.com/gobwas/glob for the full rules set.| + + +See the [GoDoc Page](https://pkg.go.dev/github.com/gohugoio/hugo@v0.93.1/tpl/resources) for the `resources` package for an up to date overview of all template functions in this namespace. + + +## Get Resource with resources.Get and resources.GetRemote + +In order to process an asset with Hugo Pipes, it must be retrieved as a `Resource` using `resources.Get` or `resources.GetRemote`. + +With `resources.Get`, the first argument is a local path relative to the `assets` directory/directories: + +```go-html-template +{{ $local := resources.Get "sass/main.scss" }} +``` + +With `resources.GetRemote`, the first argument is a remote URL: + +```go-html-template +{{ $remote := resources.GetRemote "https://www.example.com/styles.scss" }} +``` + +`resources.Get` and `resources.GetRemote` return `nil` if the resource is not found. + +### Error Handling + +{{< new-in "0.91.0" >}} + +The return value from `resources.GetRemote` includes an `.Err` method that will return an error if the call failed. If you want to just log any error as a `WARNING` you can use a construct similar to the one below. + +```go-html-template +{{ with resources.GetRemote "https://gohugo.io/images/gohugoio-card-1.png" }} + {{ with .Err }} + {{ warnf "%s" . }} + {{ else }} + <img src="{{ .RelPermalink }}" width="{{ .Width }}" height="{{ .Height }}" alt=""> + {{ end }} +{{ end }} +``` + +Note that if you do not handle `.Err` yourself, Hugo will fail the build the first time you start using the `Resource` object. + +### Remote Options + +When fetching a remote `Resource`, `resources.GetRemote` takes an optional options map as the last argument, e.g.: + +```go-html-template +{{ $resource := resources.GetRemote "https://example.org/api" (dict "headers" (dict "Authorization" "Bearer abcd")) }} +``` + +If you need multiple values for the same header key, use a slice: + +```go-html-template +{{ $resource := resources.GetRemote "https://example.org/api" (dict "headers" (dict "X-List" (slice "a" "b" "c"))) }} +``` + +You can also change the request method and set the request body: + +```go-html-template +{{ $postResponse := resources.GetRemote "https://example.org/api" (dict + "method" "post" + "body" `{"complete": true}` + "headers" (dict + "Content-Type" "application/json" + ) +)}} +``` + +### Caching of Remote Resources + +Remote resources fetched with `resources.GetRemote` will be cached on disk. See [Configure File Caches](/getting-started/configuration/#configure-file-caches) for details. + +## Asset directory + +Asset files must be stored in the asset directory. This is `/assets` by default, but can be configured via the configuration file's `assetDir` key. + +### Asset Publishing + +Hugo publishes assets to the to the `publishDir` (typically `public`) when you invoke `.Permalink`, `.RelPermalink`, or `.Publish`. You can use `.Content` to inline the asset. + +## Go Pipes + +For improved readability, the Hugo Pipes examples of this documentation will be written using [Go Pipes](/templates/introduction/#pipes): + +```go-html-template +{{ $style := resources.Get "sass/main.scss" | resources.ToCSS | resources.Minify | resources.Fingerprint }} +<link rel="stylesheet" href="{{ $style.Permalink }}"> +``` + +## Method aliases + +Each Hugo Pipes `resources` transformation method uses a __camelCased__ alias (`toCSS` for `resources.ToCSS`). +Non-transformation methods deprived of such aliases are `resources.Get`, `resources.FromString`, `resources.ExecuteAsTemplate` and `resources.Concat`. + +The example above can therefore also be written as follows: + +```go-html-template +{{ $style := resources.Get "sass/main.scss" | toCSS | minify | fingerprint }} +<link rel="stylesheet" href="{{ $style.Permalink }}"> +``` + +## Caching + +Hugo Pipes invocations are cached based on the entire _pipe chain_. + +An example of a pipe chain is: + +```go-html-template +{{ $mainJs := resources.Get "js/main.js" | js.Build "main.js" | minify | fingerprint }} +``` + +The pipe chain is only invoked the first time it is encountered in a site build, and results are otherwise loaded from cache. As such, Hugo Pipes can be used in templates which are executed thousands or millions of times without negatively impacting the build performance. diff --git a/docs/content/en/hugo-pipes/js.md b/docs/content/en/hugo-pipes/js.md new file mode 100644 index 000000000..63bd8bdd9 --- /dev/null +++ b/docs/content/en/hugo-pipes/js.md @@ -0,0 +1,171 @@ +--- +title: JavaScript Building +description: Hugo Pipes can process JavaScript files with [ESBuild](https://github.com/evanw/esbuild). +date: 2020-07-20 +publishdate: 2020-07-20 +lastmod: 2020-07-20 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 45 +weight: 45 +sections_weight: 45 +draft: false +--- + +Any JavaScript resource file can be transpiled and "tree shaken" using `js.Build` which takes for argument either a string for the filepath or a dict of options listed below. + +### Options + +targetPath [string] +: If not set, the source path will be used as the base target path. +Note that the target path's extension may change if the target MIME type is different, e.g. when the source is TypeScript. + +params [map or slice] {{< new-in "0.78.0" >}} +: Params that can be imported as JSON in your JS files, e.g.: + +```go-html-template +{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }} +``` +And then in your JS file: + +```js +import * as params from '@params'; +``` + +Note that this is meant for small data sets, e.g. config settings. For larger data, please put/mount the files into `/assets` and import them directly. + +minify [bool] +: Let `js.Build` handle the minification. + +inject [slice] {{< new-in "0.81.0" >}} +: This option allows you to automatically replace a global variable with an import from another file. The path names must be relative to `assets`. See https://esbuild.github.io/api/#inject + +shims {{< new-in "0.81.0" >}} +: This option allows swapping out a component with another. A common use case is to load dependencies like React from a CDN (with _shims_) when in production, but running with the full bundled `node_modules` dependency during development: + +``` +{{ $shims := dict "react" "js/shims/react.js" "react-dom" "js/shims/react-dom.js" }} +{{ $js = $js | js.Build dict "shims" $shims }} +``` + +The _shim_ files may look like these: + +```js +// js/shims/react.js +module.exports = window.React; +``` + +```js +// js/shims/react-dom.js +module.exports = window.ReactDOM; +``` + + +With the above, these imports should work in both scenarios: + +```js +import * as React from 'react' +import * as ReactDOM from 'react-dom'; +``` + +target [string] +: The language target. + One of: `es5`, `es2015`, `es2016`, `es2017`, `es2018`, `es2019`, `es2020` or `esnext`. + Default is `esnext`. + +externals [slice] +: External dependencies. Use this to trim dependencies you know will never be executed. See https://esbuild.github.io/api/#external + + +defines [map] +: Allow to define a set of string replacement to be performed when building. Should be a map where each key is to be replaced by its value. + +```go-html-template +{{ $defines := dict "process.env.NODE_ENV" `"development"` }} +``` + +format [string] {{< new-in "0.74.3" >}} +: The output format. + One of: `iife`, `cjs`, `esm`. + Default is `iife`, a self-executing function, suitable for inclusion as a <script> tag. + +sourceMap +: Whether to generate source maps. Enum, currently only `inline` (we will improve that). + +### Import JS code from /assets + +{{< new-in "0.78.0" >}} + +Since Hugo `v0.78.0` `js.Build` has full support for the virtual union file system in [Hugo Modules](/hugo-modules/). You can see some simple examples in this [test project](https://github.com/gohugoio/hugoTestProjectJSModImports), but in short this means that you can do this: + +```js +import { hello } from 'my/module'; +``` + +And it will resolve to the top-most `index.{js,ts,tsx,jsx}` inside `assets/my/module` in the layered file system. + +```js +import { hello3 } from 'my/module/hello3'; +``` + +Will resolve to `hello3.{js,ts,tsx,jsx}` inside `assets/my/module`. + +Any imports starting with `.` is resolved relative to the current file: + +```js +import { hello4 } from './lib'; +``` + +For other files (e.g. `JSON`, `CSS`) you need to use the relative path including any extension, e.g: + +```js +import * as data from 'my/module/data.json'; +``` + +Any imports in a file outside `/assets` or that does not resolve to a component inside `/assets` will be resolved by [ESBuild](https://esbuild.github.io/) with the **project directory** as the resolve directory (used as the starting point when looking for `node_modules` etc.). Also see [hugo mod npm pack](/commands/hugo_mod_npm_pack/). If you have any imported NPM dependencies in your project, you need to make sure to run `npm install` before you run `hugo`. + +Also note the new `params` option that can be passed from template to your JS files, e.g.: + +```go-html-template +{{ $js := resources.Get "js/main.js" | js.Build (dict "params" (dict "api" "https://example.org/api")) }} +``` +And then in your JS file: + +```js +import * as params from '@params'; +``` + +Hugo will, by default, generate a `assets/jsconfig.json` file that maps the imports. This is useful for navigation/intellisense help inside code editors, but if you don't need/want it, you can [turn it off](/getting-started/configuration/#configure-build). + + + +### Include Dependencies In package.json / node_modules + +Any imports in a file outside `/assets` or that does not resolve to a component inside `/assets` will be resolved by [ESBuild](https://esbuild.github.io/) with the **project directory** as the resolve directory (used as the starting point when looking for `node_modules` etc.). Also see [hugo mod npm pack](/commands/hugo_mod_npm_pack/). If you have any imported NPM dependencies in your project, you need to make sure to run `npm install` before you run `hugo`. + +{{< new-in "0.78.1" >}} From Hugo `0.78.1` the start directory for resolving NPM packages (aka. packages that live inside a `node_modules` folder) is always the main project folder. + +**Note:** If you're developing a theme/component that is supposed to be imported and depends on dependencies inside `package.json`, we recommend reading about [hugo mod npm pack](/commands/hugo_mod_npm_pack/), a tool to consolidate all the NPM dependencies in a project. + + +### Examples + +```go-html-template +{{ $built := resources.Get "js/index.js" | js.Build "main.js" }} +``` + +Or with options: + +```go-html-template +{{ $externals := slice "react" "react-dom" }} +{{ $defines := dict "process.env.NODE_ENV" `"development"` }} + +{{ $opts := dict "targetPath" "main.js" "externals" $externals "defines" $defines }} +{{ $built := resources.Get "scripts/main.js" | js.Build $opts }} +<script type="text/javascript" src="{{ $built.RelPermalink }}" defer></script> +``` + + diff --git a/docs/content/en/hugo-pipes/minification.md b/docs/content/en/hugo-pipes/minification.md new file mode 100755 index 000000000..d11ee58a9 --- /dev/null +++ b/docs/content/en/hugo-pipes/minification.md @@ -0,0 +1,27 @@ +--- +title: Asset minification +description: Hugo Pipes allows the minification of any CSS, JS, JSON, HTML, SVG or XML resource. +date: 2018-07-14 +publishdate: 2018-07-14 +lastmod: 2018-07-14 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 50 +weight: 50 +sections_weight: 50 +draft: false +--- + + +Any resource of the aforementioned types can be minified using `resources.Minify` which takes for argument the resource object. + + +```go-html-template +{{ $css := resources.Get "css/main.css" }} +{{ $style := $css | resources.Minify }} +``` + +Note that you can also minify the final HTML output to `/public` by running `hugo --minify`. diff --git a/docs/content/en/hugo-pipes/postcss.md b/docs/content/en/hugo-pipes/postcss.md new file mode 100755 index 000000000..fddc7e9cf --- /dev/null +++ b/docs/content/en/hugo-pipes/postcss.md @@ -0,0 +1,84 @@ +--- +title: PostCSS +description: Hugo Pipes can process CSS files with PostCSS. +date: 2018-07-14 +publishdate: 2018-07-14 +lastmod: 2018-07-14 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 40 +weight: 40 +sections_weight: 40 +draft: false +--- + +Any asset file can be processed using `resources.PostCSS` which takes for argument the resource object and a slice of options listed below. + +The resource will be processed using the project's or theme's own `postcss.config.js` or any file set with the `config` option. + +```go-html-template +{{ $css := resources.Get "css/main.css" }} +{{ $style := $css | resources.PostCSS }} +``` + +{{% note %}} +Hugo Pipe's PostCSS requires the `postcss-cli` JavaScript package to be installed in the environment (`npm install -g postcss postcss-cli`) along with any PostCSS plugin(s) used (e.g., `npm install -g autoprefixer`). + +If you are using the Hugo Snap package, PostCSS and plugin(s) need to be installed locally within your Hugo site directory, e.g., `npm install postcss-cli` without the `-g` flag. +{{% /note %}} + +### Options + +config [string] +: Path to the PostCSS configuration file + +noMap [bool] +: Default is `false`. Disable the default inline sourcemaps + +inlineImports [bool] {{< new-in "0.66.0" >}} +: 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. + +_If no configuration file is used:_ + +use [string] +: Space-delimited list of PostCSS plugins to use + +parser [string] +: Custom PostCSS parser + +stringifier [string] +: Custom PostCSS stringifier + +syntax [string] +: Custom postcss syntax + +```go-html-template +{{ $options := dict "config" "customPostCSS.js" "noMap" true }} +{{ $style := resources.Get "css/main.css" | resources.PostCSS $options }} + +{{ $options := dict "use" "autoprefixer postcss-color-alpha" }} +{{ $style := resources.Get "css/main.css" | resources.PostCSS $options }} +``` + +## Check Hugo Environment from postcss.config.js + +{{< new-in "0.66.0" >}} + +The current Hugo environment name (set by `--environment` or in config or OS environment) is available in the Node context, which allows constructs like this: + +```js +module.exports = { + plugins: [ + require('autoprefixer'), + ...process.env.HUGO_ENVIRONMENT === 'production' + ? [purgecss] + : [] + ] +} +``` diff --git a/docs/content/en/hugo-pipes/postprocess.md b/docs/content/en/hugo-pipes/postprocess.md new file mode 100755 index 000000000..aafb786a4 --- /dev/null +++ b/docs/content/en/hugo-pipes/postprocess.md @@ -0,0 +1,70 @@ +--- +title: PostProcess +description: Allows delaying of resource transformations to after the build. +date: 2020-04-09 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 39 +weight: 39 +sections_weight: 39 +--- + +Marking a resource with `resources.PostProcess` delays any transformations to after the build, typically because one or more of the steps in the transformation chain depends on the result of the build (e.g. files in `public`).{{< new-in "0.69.0" >}} + +A prime use case for this is [CSS purging with PostCSS](#css-purging-with-postcss). + +There are currently two limitations to this: + +1. This only works in `*.html` templates (i.e. templates that produces HTML files). +2. You cannot manipulate the values returned from the resource's methods. E.g. the `upper` 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 | upper }} + ``` + +## CSS purging with PostCSS + +{{% 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 some examples. +{{% /note %}} + +The below configuration will write a `hugo_stats.json` file to the project root as part of the build. If you're only using this for the production build, you should consider placing it below [config/production](/getting-started/configuration/#configuration-directory). + +{{< code-toggle file="config" >}} +[build] + writeStats = true +{{< /code-toggle >}} + +`postcss.config.js` + +```js +const purgecss = require('@fullhuman/postcss-purgecss')({ + content: [ './hugo_stats.json' ], + defaultExtractor: (content) => { + let els = JSON.parse(content).htmlElements; + return els.tags.concat(els.classes, els.ids); + } +}); + +module.exports = { + plugins: [ + ...(process.env.HUGO_ENVIRONMENT === 'production' ? [ purgecss ] : []) + ] + }; +``` + +Note that in the example above, the "CSS purge step" will only be applied to the production build. This means that you need to do something like this in your head template to build and include your CSS: + +```go-html-template +{{ $css := resources.Get "css/main.css" }} +{{ $css = $css | resources.PostCSS }} +{{ if hugo.IsProduction }} +{{ $css = $css | minify | fingerprint | resources.PostProcess }} +{{ end }} +<link href="{{ $css.RelPermalink }}" rel="stylesheet" /> +``` diff --git a/docs/content/en/hugo-pipes/resource-from-string.md b/docs/content/en/hugo-pipes/resource-from-string.md new file mode 100755 index 000000000..8b942d2f3 --- /dev/null +++ b/docs/content/en/hugo-pipes/resource-from-string.md @@ -0,0 +1,31 @@ +--- +title: Creating a resource from a string +linkTitle: Resource from String +description: Hugo Pipes allows the creation of a resource from a string. +date: 2018-07-14 +publishdate: 2018-07-14 +lastmod: 2018-07-14 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 90 +weight: 90 +sections_weight: 90 +draft: false +--- + +It is possible to create a resource directly from the template using `resources.FromString` which takes two arguments, the given string and the resource target path. + +The following example creates a resource file containing localized variables for every project's languages. + +```go-html-template +{{ $string := (printf "var rootURL = '%s'; var apiURL = '%s';" (absURL "/") (.Param "API_URL")) }} +{{ $targetPath := "js/vars.js" }} +{{ $vars := $string | resources.FromString $targetPath }} +{{ $global := resources.Get "js/global.js" | resources.Minify }} + +<script type="text/javascript" src="{{ $vars.Permalink }}"></script> +<script type="text/javascript" src="{{ $global.Permalink }}"></script> +``` diff --git a/docs/content/en/hugo-pipes/resource-from-template.md b/docs/content/en/hugo-pipes/resource-from-template.md new file mode 100755 index 000000000..9bc8c7e9d --- /dev/null +++ b/docs/content/en/hugo-pipes/resource-from-template.md @@ -0,0 +1,38 @@ +--- +title: Creating a resource from template +linkTitle: Resource from Template +description: Hugo Pipes allows the creation of a resource from an asset file using Go Template. +date: 2018-07-14 +publishdate: 2018-07-14 +lastmod: 2018-07-14 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 80 +weight: 80 +sections_weight: 80 +draft: false +--- + +In order to use Hugo Pipes function on an asset file containing Go Template magic the function `resources.ExecuteAsTemplate` must be used. + +The function takes three arguments: the resource target path, the template context, and the resource object. + +```go-html-template +// assets/sass/template.scss +$backgroundColor: {{ .Param "backgroundColor" }}; +$textColor: {{ .Param "textColor" }}; +body{ + background-color:$backgroundColor; + color: $textColor; +} +// [...] +``` + + +```go-html-template +{{ $sassTemplate := resources.Get "sass/template.scss" }} +{{ $style := $sassTemplate | resources.ExecuteAsTemplate "main.scss" . | resources.ToCSS }} +``` diff --git a/docs/content/en/hugo-pipes/scss-sass.md b/docs/content/en/hugo-pipes/scss-sass.md new file mode 100755 index 000000000..12cebc014 --- /dev/null +++ b/docs/content/en/hugo-pipes/scss-sass.md @@ -0,0 +1,54 @@ +--- +title: SASS / SCSS +description: Hugo Pipes allows the processing of SASS and SCSS files. +date: 2018-07-14 +publishdate: 2018-07-14 +lastmod: 2018-07-14 +categories: [asset management] +keywords: [] +menu: + docs: + parent: "pipes" + weight: 30 +weight: 02 +sections_weight: 02 +draft: false +--- + + +Any SASS or SCSS file can be transformed into a CSS file using `resources.ToCSS` which takes two arguments, the resource object and a map of options listed below. + +```go-html-template +{{ $sass := resources.Get "sass/main.scss" }} +{{ $style := $sass | resources.ToCSS }} +``` + +### Options + +transpiler [string] {{< new-in "0.80.0" >}} + +: The `transpiler` to use, valid values are `libsass` (default) and `dartsass`. Note that the Embedded Dart Sass project is still in beta. We will try to improve the installation process when it has stable releases, but if you want to use Hugo with Dart Sass you need to download a release binary from [Embedded Dart Sass](https://github.com/sass/dart-sass-embedded/releases) (Hugo after 0.81.0 requires beta 6 or newer) and make sure it's in your PC's `$PATH` (or `%PATH%` on Windows). + +targetPath [string] +: If not set, the resource's target path will be the asset file original path with its extension replaced by `.css`. + +outputStyle [string] +: Default is `nested` (LibSass) and `expanded` (Dart Sass). Other available output styles for LibSass are `expanded`, `compact` and `compressed`. Dart Sass only supports `expanded` and `compressed`. + +precision [int] +: Precision of floating point math. **Note:** This option is not supported by Dart Sass. + +enableSourceMap [bool] +: When enabled, a source map will be generated. + +includePaths [string slice] +: Additional SCSS/SASS include paths. Paths must be relative to the project directory. + +```go-html-template +{{ $options := (dict "targetPath" "style.css" "outputStyle" "compressed" "enableSourceMap" true "includePaths" (slice "node_modules/myscss")) }} +{{ $style := resources.Get "sass/main.scss" | resources.ToCSS $options }} +``` + +{{% note %}} +Setting `outputStyle` to `compressed` will handle SASS/SCSS files minification better than the more generic [`resources.Minify`]({{< ref "minification">}}). +{{% /note %}} |