2017-01-10 04:55:03 -05:00
|
|
|
package deps
|
|
|
|
|
|
|
|
import (
|
2023-03-04 08:43:23 -05:00
|
|
|
"context"
|
2022-05-02 10:07:52 -04:00
|
|
|
"fmt"
|
2023-06-16 02:17:42 -04:00
|
|
|
"io"
|
2022-09-26 11:34:20 -04:00
|
|
|
"path/filepath"
|
2023-01-04 12:24:36 -05:00
|
|
|
"sort"
|
2022-09-26 11:34:20 -04:00
|
|
|
"strings"
|
2018-07-11 13:23:22 -04:00
|
|
|
"sync"
|
2020-02-25 15:40:02 -05:00
|
|
|
"sync/atomic"
|
2017-01-10 04:55:03 -05:00
|
|
|
|
2023-06-16 02:17:42 -04:00
|
|
|
"github.com/bep/logg"
|
2021-12-12 06:11:11 -05:00
|
|
|
"github.com/gohugoio/hugo/common/hexec"
|
Add Hugo Piper with SCSS support and much more
Before this commit, you would have to use page bundles to do image processing etc. in Hugo.
This commit adds
* A new `/assets` top-level project or theme dir (configurable via `assetDir`)
* A new template func, `resources.Get` which can be used to "get a resource" that can be further processed.
This means that you can now do this in your templates (or shortcodes):
```bash
{{ $sunset := (resources.Get "images/sunset.jpg").Fill "300x200" }}
```
This also adds a new `extended` build tag that enables powerful SCSS/SASS support with source maps. To compile this from source, you will also need a C compiler installed:
```
HUGO_BUILD_TAGS=extended mage install
```
Note that you can use output of the SCSS processing later in a non-SCSSS-enabled Hugo.
The `SCSS` processor is a _Resource transformation step_ and it can be chained with the many others in a pipeline:
```bash
{{ $css := resources.Get "styles.scss" | resources.ToCSS | resources.PostCSS | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
The transformation funcs above have aliases, so it can be shortened to:
```bash
{{ $css := resources.Get "styles.scss" | toCSS | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
A quick tip would be to avoid the fingerprinting part, and possibly also the not-superfast `postCSS` when you're doing development, as it allows Hugo to be smarter about the rebuilding.
Documentation will follow, but have a look at the demo repo in https://github.com/bep/hugo-sass-test
New functions to create `Resource` objects:
* `resources.Get` (see above)
* `resources.FromString`: Create a Resource from a string.
New `Resource` transformation funcs:
* `resources.ToCSS`: Compile `SCSS` or `SASS` into `CSS`.
* `resources.PostCSS`: Process your CSS with PostCSS. Config file support (project or theme or passed as an option).
* `resources.Minify`: Currently supports `css`, `js`, `json`, `html`, `svg`, `xml`.
* `resources.Fingerprint`: Creates a fingerprinted version of the given Resource with Subresource Integrity..
* `resources.Concat`: Concatenates a list of Resource objects. Think of this as a poor man's bundler.
* `resources.ExecuteAsTemplate`: Parses and executes the given Resource and data context (e.g. .Site) as a Go template.
Fixes #4381
Fixes #4903
Fixes #4858
2018-02-20 04:02:14 -05:00
|
|
|
"github.com/gohugoio/hugo/common/loggers"
|
2017-06-13 12:42:45 -04:00
|
|
|
"github.com/gohugoio/hugo/config"
|
2023-01-04 12:24:36 -05:00
|
|
|
"github.com/gohugoio/hugo/config/allconfig"
|
2021-12-12 06:11:11 -05:00
|
|
|
"github.com/gohugoio/hugo/config/security"
|
2017-06-13 12:42:45 -04:00
|
|
|
"github.com/gohugoio/hugo/helpers"
|
|
|
|
"github.com/gohugoio/hugo/hugofs"
|
Add Hugo Piper with SCSS support and much more
Before this commit, you would have to use page bundles to do image processing etc. in Hugo.
This commit adds
* A new `/assets` top-level project or theme dir (configurable via `assetDir`)
* A new template func, `resources.Get` which can be used to "get a resource" that can be further processed.
This means that you can now do this in your templates (or shortcodes):
```bash
{{ $sunset := (resources.Get "images/sunset.jpg").Fill "300x200" }}
```
This also adds a new `extended` build tag that enables powerful SCSS/SASS support with source maps. To compile this from source, you will also need a C compiler installed:
```
HUGO_BUILD_TAGS=extended mage install
```
Note that you can use output of the SCSS processing later in a non-SCSSS-enabled Hugo.
The `SCSS` processor is a _Resource transformation step_ and it can be chained with the many others in a pipeline:
```bash
{{ $css := resources.Get "styles.scss" | resources.ToCSS | resources.PostCSS | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
The transformation funcs above have aliases, so it can be shortened to:
```bash
{{ $css := resources.Get "styles.scss" | toCSS | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
A quick tip would be to avoid the fingerprinting part, and possibly also the not-superfast `postCSS` when you're doing development, as it allows Hugo to be smarter about the rebuilding.
Documentation will follow, but have a look at the demo repo in https://github.com/bep/hugo-sass-test
New functions to create `Resource` objects:
* `resources.Get` (see above)
* `resources.FromString`: Create a Resource from a string.
New `Resource` transformation funcs:
* `resources.ToCSS`: Compile `SCSS` or `SASS` into `CSS`.
* `resources.PostCSS`: Process your CSS with PostCSS. Config file support (project or theme or passed as an option).
* `resources.Minify`: Currently supports `css`, `js`, `json`, `html`, `svg`, `xml`.
* `resources.Fingerprint`: Creates a fingerprinted version of the given Resource with Subresource Integrity..
* `resources.Concat`: Concatenates a list of Resource objects. Think of this as a poor man's bundler.
* `resources.ExecuteAsTemplate`: Parses and executes the given Resource and data context (e.g. .Site) as a Go template.
Fixes #4381
Fixes #4903
Fixes #4858
2018-02-20 04:02:14 -05:00
|
|
|
"github.com/gohugoio/hugo/media"
|
2019-01-02 06:33:26 -05:00
|
|
|
"github.com/gohugoio/hugo/resources/page"
|
2022-09-14 05:58:45 -04:00
|
|
|
"github.com/gohugoio/hugo/resources/postpub"
|
2019-01-02 06:33:26 -05:00
|
|
|
|
2017-09-26 14:03:04 -04:00
|
|
|
"github.com/gohugoio/hugo/metrics"
|
2019-01-02 05:58:32 -05:00
|
|
|
"github.com/gohugoio/hugo/resources"
|
:sparkles: Implement Page bundling and image handling
This commit is not the smallest in Hugo's history.
Some hightlights include:
* Page bundles (for complete articles, keeping images and content together etc.).
* Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`.
* Processed images are cached inside `resources/_gen/images` (default) in your project.
* Symbolic links (both files and dirs) are now allowed anywhere inside /content
* A new table based build summary
* The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below).
A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory:
```bash
▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render"
benchmark old ns/op new ns/op delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86%
benchmark old allocs new allocs delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30%
benchmark old bytes new bytes delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64%
```
Fixes #3651
Closes #3158
Fixes #1014
Closes #2021
Fixes #1240
Updates #3757
2017-07-24 03:00:23 -04:00
|
|
|
"github.com/gohugoio/hugo/source"
|
2017-06-13 12:42:45 -04:00
|
|
|
"github.com/gohugoio/hugo/tpl"
|
2023-01-04 12:24:36 -05:00
|
|
|
"github.com/spf13/afero"
|
2017-01-10 04:55:03 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
// Deps holds dependencies used by many.
|
2017-08-02 08:25:05 -04:00
|
|
|
// There will be normally only one instance of deps in play
|
2017-01-10 04:55:03 -05:00
|
|
|
// at a given time, i.e. one per Site built.
|
|
|
|
type Deps struct {
|
|
|
|
// The logger to use.
|
2020-10-21 05:17:48 -04:00
|
|
|
Log loggers.Logger `json:"-"`
|
2017-01-10 04:55:03 -05:00
|
|
|
|
2021-12-12 06:11:11 -05:00
|
|
|
ExecHelper *hexec.Exec
|
|
|
|
|
2019-12-10 13:56:44 -05:00
|
|
|
// The templates to use. This will usually implement the full tpl.TemplateManager.
|
2023-01-04 12:24:36 -05:00
|
|
|
tmplHandlers *tpl.TemplateHandlers
|
Add Hugo Piper with SCSS support and much more
Before this commit, you would have to use page bundles to do image processing etc. in Hugo.
This commit adds
* A new `/assets` top-level project or theme dir (configurable via `assetDir`)
* A new template func, `resources.Get` which can be used to "get a resource" that can be further processed.
This means that you can now do this in your templates (or shortcodes):
```bash
{{ $sunset := (resources.Get "images/sunset.jpg").Fill "300x200" }}
```
This also adds a new `extended` build tag that enables powerful SCSS/SASS support with source maps. To compile this from source, you will also need a C compiler installed:
```
HUGO_BUILD_TAGS=extended mage install
```
Note that you can use output of the SCSS processing later in a non-SCSSS-enabled Hugo.
The `SCSS` processor is a _Resource transformation step_ and it can be chained with the many others in a pipeline:
```bash
{{ $css := resources.Get "styles.scss" | resources.ToCSS | resources.PostCSS | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
The transformation funcs above have aliases, so it can be shortened to:
```bash
{{ $css := resources.Get "styles.scss" | toCSS | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
A quick tip would be to avoid the fingerprinting part, and possibly also the not-superfast `postCSS` when you're doing development, as it allows Hugo to be smarter about the rebuilding.
Documentation will follow, but have a look at the demo repo in https://github.com/bep/hugo-sass-test
New functions to create `Resource` objects:
* `resources.Get` (see above)
* `resources.FromString`: Create a Resource from a string.
New `Resource` transformation funcs:
* `resources.ToCSS`: Compile `SCSS` or `SASS` into `CSS`.
* `resources.PostCSS`: Process your CSS with PostCSS. Config file support (project or theme or passed as an option).
* `resources.Minify`: Currently supports `css`, `js`, `json`, `html`, `svg`, `xml`.
* `resources.Fingerprint`: Creates a fingerprinted version of the given Resource with Subresource Integrity..
* `resources.Concat`: Concatenates a list of Resource objects. Think of this as a poor man's bundler.
* `resources.ExecuteAsTemplate`: Parses and executes the given Resource and data context (e.g. .Site) as a Go template.
Fixes #4381
Fixes #4903
Fixes #4858
2018-02-20 04:02:14 -05:00
|
|
|
|
2017-01-10 04:55:03 -05:00
|
|
|
// The file systems to use.
|
|
|
|
Fs *hugofs.Fs `json:"-"`
|
|
|
|
|
|
|
|
// The PathSpec to use
|
|
|
|
*helpers.PathSpec `json:"-"`
|
|
|
|
|
2017-02-04 22:20:06 -05:00
|
|
|
// The ContentSpec to use
|
|
|
|
*helpers.ContentSpec `json:"-"`
|
|
|
|
|
:sparkles: Implement Page bundling and image handling
This commit is not the smallest in Hugo's history.
Some hightlights include:
* Page bundles (for complete articles, keeping images and content together etc.).
* Bundled images can be processed in as many versions/sizes as you need with the three methods `Resize`, `Fill` and `Fit`.
* Processed images are cached inside `resources/_gen/images` (default) in your project.
* Symbolic links (both files and dirs) are now allowed anywhere inside /content
* A new table based build summary
* The "Total in nn ms" now reports the total including the handling of the files inside /static. So if it now reports more than you're used to, it is just **more real** and probably faster than before (see below).
A site building benchmark run compared to `v0.31.1` shows that this should be slightly faster and use less memory:
```bash
▶ ./benchSite.sh "TOML,num_langs=.*,num_root_sections=5,num_pages=(500|1000),tags_per_page=5,shortcodes,render"
benchmark old ns/op new ns/op delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 101785785 78067944 -23.30%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 185481057 149159919 -19.58%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 103149918 85679409 -16.94%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 203515478 169208775 -16.86%
benchmark old allocs new allocs delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 532464 391539 -26.47%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1056549 772702 -26.87%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 555974 406630 -26.86%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 1086545 789922 -27.30%
benchmark old bytes new bytes delta
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 53243246 43598155 -18.12%
BenchmarkSiteBuilding/TOML,num_langs=1,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 105811617 86087116 -18.64%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=500,tags_per_page=5,shortcodes,render-4 54558852 44545097 -18.35%
BenchmarkSiteBuilding/TOML,num_langs=3,num_root_sections=5,num_pages=1000,tags_per_page=5,shortcodes,render-4 106903858 86978413 -18.64%
```
Fixes #3651
Closes #3158
Fixes #1014
Closes #2021
Fixes #1240
Updates #3757
2017-07-24 03:00:23 -04:00
|
|
|
// The SourceSpec to use
|
|
|
|
SourceSpec *source.SourceSpec `json:"-"`
|
|
|
|
|
Add Hugo Piper with SCSS support and much more
Before this commit, you would have to use page bundles to do image processing etc. in Hugo.
This commit adds
* A new `/assets` top-level project or theme dir (configurable via `assetDir`)
* A new template func, `resources.Get` which can be used to "get a resource" that can be further processed.
This means that you can now do this in your templates (or shortcodes):
```bash
{{ $sunset := (resources.Get "images/sunset.jpg").Fill "300x200" }}
```
This also adds a new `extended` build tag that enables powerful SCSS/SASS support with source maps. To compile this from source, you will also need a C compiler installed:
```
HUGO_BUILD_TAGS=extended mage install
```
Note that you can use output of the SCSS processing later in a non-SCSSS-enabled Hugo.
The `SCSS` processor is a _Resource transformation step_ and it can be chained with the many others in a pipeline:
```bash
{{ $css := resources.Get "styles.scss" | resources.ToCSS | resources.PostCSS | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
The transformation funcs above have aliases, so it can be shortened to:
```bash
{{ $css := resources.Get "styles.scss" | toCSS | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
A quick tip would be to avoid the fingerprinting part, and possibly also the not-superfast `postCSS` when you're doing development, as it allows Hugo to be smarter about the rebuilding.
Documentation will follow, but have a look at the demo repo in https://github.com/bep/hugo-sass-test
New functions to create `Resource` objects:
* `resources.Get` (see above)
* `resources.FromString`: Create a Resource from a string.
New `Resource` transformation funcs:
* `resources.ToCSS`: Compile `SCSS` or `SASS` into `CSS`.
* `resources.PostCSS`: Process your CSS with PostCSS. Config file support (project or theme or passed as an option).
* `resources.Minify`: Currently supports `css`, `js`, `json`, `html`, `svg`, `xml`.
* `resources.Fingerprint`: Creates a fingerprinted version of the given Resource with Subresource Integrity..
* `resources.Concat`: Concatenates a list of Resource objects. Think of this as a poor man's bundler.
* `resources.ExecuteAsTemplate`: Parses and executes the given Resource and data context (e.g. .Site) as a Go template.
Fixes #4381
Fixes #4903
Fixes #4858
2018-02-20 04:02:14 -05:00
|
|
|
// The Resource Spec to use
|
2019-01-02 05:58:32 -05:00
|
|
|
ResourceSpec *resources.Spec
|
Add Hugo Piper with SCSS support and much more
Before this commit, you would have to use page bundles to do image processing etc. in Hugo.
This commit adds
* A new `/assets` top-level project or theme dir (configurable via `assetDir`)
* A new template func, `resources.Get` which can be used to "get a resource" that can be further processed.
This means that you can now do this in your templates (or shortcodes):
```bash
{{ $sunset := (resources.Get "images/sunset.jpg").Fill "300x200" }}
```
This also adds a new `extended` build tag that enables powerful SCSS/SASS support with source maps. To compile this from source, you will also need a C compiler installed:
```
HUGO_BUILD_TAGS=extended mage install
```
Note that you can use output of the SCSS processing later in a non-SCSSS-enabled Hugo.
The `SCSS` processor is a _Resource transformation step_ and it can be chained with the many others in a pipeline:
```bash
{{ $css := resources.Get "styles.scss" | resources.ToCSS | resources.PostCSS | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
The transformation funcs above have aliases, so it can be shortened to:
```bash
{{ $css := resources.Get "styles.scss" | toCSS | postCSS | minify | fingerprint }}
<link rel="stylesheet" href="{{ $styles.RelPermalink }}" integrity="{{ $styles.Data.Digest }}" media="screen">
```
A quick tip would be to avoid the fingerprinting part, and possibly also the not-superfast `postCSS` when you're doing development, as it allows Hugo to be smarter about the rebuilding.
Documentation will follow, but have a look at the demo repo in https://github.com/bep/hugo-sass-test
New functions to create `Resource` objects:
* `resources.Get` (see above)
* `resources.FromString`: Create a Resource from a string.
New `Resource` transformation funcs:
* `resources.ToCSS`: Compile `SCSS` or `SASS` into `CSS`.
* `resources.PostCSS`: Process your CSS with PostCSS. Config file support (project or theme or passed as an option).
* `resources.Minify`: Currently supports `css`, `js`, `json`, `html`, `svg`, `xml`.
* `resources.Fingerprint`: Creates a fingerprinted version of the given Resource with Subresource Integrity..
* `resources.Concat`: Concatenates a list of Resource objects. Think of this as a poor man's bundler.
* `resources.ExecuteAsTemplate`: Parses and executes the given Resource and data context (e.g. .Site) as a Go template.
Fixes #4381
Fixes #4903
Fixes #4858
2018-02-20 04:02:14 -05:00
|
|
|
|
2017-02-04 22:20:06 -05:00
|
|
|
// The configuration to use
|
2023-01-04 12:24:36 -05:00
|
|
|
Conf config.AllProvider `json:"-"`
|
2018-11-08 04:24:13 -05:00
|
|
|
|
2017-02-04 22:20:06 -05:00
|
|
|
// The translation func to use
|
2023-03-04 08:43:23 -05:00
|
|
|
Translate func(ctx context.Context, translationID string, templateData any) string `json:"-"`
|
2017-02-04 22:20:06 -05:00
|
|
|
|
2018-11-26 04:11:22 -05:00
|
|
|
// The site building.
|
2019-01-02 06:33:26 -05:00
|
|
|
Site page.Site
|
2018-11-26 04:11:22 -05:00
|
|
|
|
2023-01-04 12:24:36 -05:00
|
|
|
TemplateProvider ResourceProvider
|
2019-12-10 13:56:44 -05:00
|
|
|
// Used in tests
|
2022-03-17 17:03:27 -04:00
|
|
|
OverloadedTemplateFuncs map[string]any
|
2017-01-10 04:55:03 -05:00
|
|
|
|
2023-01-04 12:24:36 -05:00
|
|
|
TranslationProvider ResourceProvider
|
2017-09-26 14:03:04 -04:00
|
|
|
|
|
|
|
Metrics metrics.Provider
|
2018-04-19 12:06:40 -04:00
|
|
|
|
2018-07-11 13:23:22 -04:00
|
|
|
// BuildStartListeners will be notified before a build starts.
|
|
|
|
BuildStartListeners *Listeners
|
2018-10-21 06:20:21 -04:00
|
|
|
|
2023-10-19 04:53:27 -04:00
|
|
|
// BuildEndListeners will be notified after a build finishes.
|
|
|
|
BuildEndListeners *Listeners
|
|
|
|
|
2020-12-23 03:26:23 -05:00
|
|
|
// Resources that gets closed when the build is done or the server shuts down.
|
|
|
|
BuildClosers *Closers
|
|
|
|
|
2020-02-25 15:40:02 -05:00
|
|
|
// This is common/global for all sites.
|
|
|
|
BuildState *BuildState
|
2020-01-15 09:59:56 -05:00
|
|
|
|
2018-10-21 06:20:21 -04:00
|
|
|
*globalErrHandler
|
|
|
|
}
|
|
|
|
|
2023-01-04 12:24:36 -05:00
|
|
|
func (d Deps) Clone(s page.Site, conf config.AllProvider) (*Deps, error) {
|
|
|
|
d.Conf = conf
|
|
|
|
d.Site = s
|
|
|
|
d.ExecHelper = nil
|
|
|
|
d.ContentSpec = nil
|
|
|
|
|
|
|
|
if err := d.Init(); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return &d, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Deps) SetTempl(t *tpl.TemplateHandlers) {
|
|
|
|
d.tmplHandlers = t
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Deps) Init() error {
|
|
|
|
if d.Conf == nil {
|
|
|
|
panic("conf is nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.Fs == nil {
|
|
|
|
// For tests.
|
|
|
|
d.Fs = hugofs.NewFrom(afero.NewMemMapFs(), d.Conf.BaseConfig())
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.Log == nil {
|
2023-06-16 02:17:42 -04:00
|
|
|
d.Log = loggers.NewDefault()
|
2023-01-04 12:24:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if d.globalErrHandler == nil {
|
2023-06-16 02:17:42 -04:00
|
|
|
d.globalErrHandler = &globalErrHandler{
|
|
|
|
logger: d.Log,
|
|
|
|
}
|
2023-01-04 12:24:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if d.BuildState == nil {
|
|
|
|
d.BuildState = &BuildState{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.BuildStartListeners == nil {
|
|
|
|
d.BuildStartListeners = &Listeners{}
|
|
|
|
}
|
|
|
|
|
2023-10-19 04:53:27 -04:00
|
|
|
if d.BuildEndListeners == nil {
|
|
|
|
d.BuildEndListeners = &Listeners{}
|
|
|
|
}
|
|
|
|
|
2023-01-04 12:24:36 -05:00
|
|
|
if d.BuildClosers == nil {
|
|
|
|
d.BuildClosers = &Closers{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.Metrics == nil && d.Conf.TemplateMetrics() {
|
|
|
|
d.Metrics = metrics.NewProvider(d.Conf.TemplateMetricsHints())
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.ExecHelper == nil {
|
|
|
|
d.ExecHelper = hexec.New(d.Conf.GetConfigSection("security").(security.Config))
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.PathSpec == nil {
|
|
|
|
hashBytesReceiverFunc := func(name string, match bool) {
|
|
|
|
if !match {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
d.BuildState.AddFilenameWithPostPrefix(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip binary files.
|
|
|
|
mediaTypes := d.Conf.GetConfigSection("mediaTypes").(media.Types)
|
|
|
|
hashBytesSHouldCheck := func(name string) bool {
|
|
|
|
ext := strings.TrimPrefix(filepath.Ext(name), ".")
|
|
|
|
return mediaTypes.IsTextSuffix(ext)
|
|
|
|
}
|
|
|
|
d.Fs.PublishDir = hugofs.NewHasBytesReceiver(d.Fs.PublishDir, hashBytesSHouldCheck, hashBytesReceiverFunc, []byte(postpub.PostProcessPrefix))
|
|
|
|
pathSpec, err := helpers.NewPathSpec(d.Fs, d.Conf, d.Log)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
d.PathSpec = pathSpec
|
|
|
|
} else {
|
|
|
|
var err error
|
|
|
|
d.PathSpec, err = helpers.NewPathSpecWithBaseBaseFsProvided(d.Fs, d.Conf, d.Log, d.PathSpec.BaseFs)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.ContentSpec == nil {
|
|
|
|
contentSpec, err := helpers.NewContentSpec(d.Conf, d.Log, d.Content.Fs, d.ExecHelper)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
d.ContentSpec = contentSpec
|
|
|
|
}
|
|
|
|
|
|
|
|
if d.SourceSpec == nil {
|
|
|
|
d.SourceSpec = source.NewSourceSpec(d.PathSpec, nil, d.Fs.Source)
|
|
|
|
}
|
|
|
|
|
|
|
|
var common *resources.SpecCommon
|
2023-05-28 05:35:00 -04:00
|
|
|
var imageCache *resources.ImageCache
|
2023-01-04 12:24:36 -05:00
|
|
|
if d.ResourceSpec != nil {
|
|
|
|
common = d.ResourceSpec.SpecCommon
|
2023-05-28 05:35:00 -04:00
|
|
|
imageCache = d.ResourceSpec.ImageCache
|
2023-01-04 12:24:36 -05:00
|
|
|
}
|
2023-05-28 05:35:00 -04:00
|
|
|
|
|
|
|
resourceSpec, err := resources.NewSpec(d.PathSpec, common, imageCache, d.BuildState, d.Log, d, d.ExecHelper)
|
2023-01-04 12:24:36 -05:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to create resource spec: %w", err)
|
|
|
|
}
|
|
|
|
d.ResourceSpec = resourceSpec
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Deps) Compile(prototype *Deps) error {
|
|
|
|
var err error
|
|
|
|
if prototype == nil {
|
|
|
|
if err = d.TemplateProvider.NewResource(d); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err = d.TranslationProvider.NewResource(d); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = d.TemplateProvider.CloneResource(d, prototype); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if err = d.TranslationProvider.CloneResource(d, prototype); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2018-10-21 06:20:21 -04:00
|
|
|
type globalErrHandler struct {
|
2023-06-16 02:17:42 -04:00
|
|
|
logger loggers.Logger
|
|
|
|
|
2018-10-21 06:20:21 -04:00
|
|
|
// Channel for some "hard to get to" build errors
|
|
|
|
buildErrors chan error
|
2023-04-13 05:44:22 -04:00
|
|
|
// Used to signal that the build is done.
|
|
|
|
quit chan struct{}
|
2018-10-21 06:20:21 -04:00
|
|
|
}
|
|
|
|
|
2023-05-18 05:05:56 -04:00
|
|
|
// SendError sends the error on a channel to be handled later.
|
2018-10-21 06:20:21 -04:00
|
|
|
// This can be used in situations where returning and aborting the current
|
|
|
|
// operation isn't practical.
|
|
|
|
func (e *globalErrHandler) SendError(err error) {
|
|
|
|
if e.buildErrors != nil {
|
|
|
|
select {
|
2023-04-13 05:44:22 -04:00
|
|
|
case <-e.quit:
|
2018-10-21 06:20:21 -04:00
|
|
|
case e.buildErrors <- err:
|
|
|
|
default:
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2023-06-16 02:17:42 -04:00
|
|
|
e.logger.Errorln(err)
|
2018-10-21 06:20:21 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *globalErrHandler) StartErrorCollector() chan error {
|
2023-04-13 05:44:22 -04:00
|
|
|
e.quit = make(chan struct{})
|
2018-10-21 06:20:21 -04:00
|
|
|
e.buildErrors = make(chan error, 10)
|
|
|
|
return e.buildErrors
|
2018-07-11 13:23:22 -04:00
|
|
|
}
|
|
|
|
|
2023-04-13 05:44:22 -04:00
|
|
|
func (e *globalErrHandler) StopErrorCollector() {
|
|
|
|
if e.buildErrors != nil {
|
|
|
|
close(e.quit)
|
|
|
|
close(e.buildErrors)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-06 14:23:56 -04:00
|
|
|
// Listeners represents an event listener.
|
2018-07-11 13:23:22 -04:00
|
|
|
type Listeners struct {
|
|
|
|
sync.Mutex
|
|
|
|
|
|
|
|
// A list of funcs to be notified about an event.
|
|
|
|
listeners []func()
|
|
|
|
}
|
|
|
|
|
2018-09-06 14:23:56 -04:00
|
|
|
// Add adds a function to a Listeners instance.
|
2018-07-11 13:23:22 -04:00
|
|
|
func (b *Listeners) Add(f func()) {
|
2018-12-21 10:21:13 -05:00
|
|
|
if b == nil {
|
|
|
|
return
|
|
|
|
}
|
2018-07-11 13:23:22 -04:00
|
|
|
b.Lock()
|
|
|
|
defer b.Unlock()
|
|
|
|
b.listeners = append(b.listeners, f)
|
|
|
|
}
|
|
|
|
|
2018-09-06 14:23:56 -04:00
|
|
|
// Notify executes all listener functions.
|
2018-07-11 13:23:22 -04:00
|
|
|
func (b *Listeners) Notify() {
|
|
|
|
b.Lock()
|
|
|
|
defer b.Unlock()
|
|
|
|
for _, notify := range b.listeners {
|
|
|
|
notify()
|
|
|
|
}
|
2017-01-10 04:55:03 -05:00
|
|
|
}
|
|
|
|
|
2017-03-09 08:18:12 -05:00
|
|
|
// ResourceProvider is used to create and refresh, and clone resources needed.
|
2017-02-04 22:20:06 -05:00
|
|
|
type ResourceProvider interface {
|
2023-01-04 12:24:36 -05:00
|
|
|
NewResource(dst *Deps) error
|
|
|
|
CloneResource(dst, src *Deps) error
|
2017-01-10 04:55:03 -05:00
|
|
|
}
|
|
|
|
|
2020-01-15 09:59:56 -05:00
|
|
|
func (d *Deps) Tmpl() tpl.TemplateHandler {
|
2023-01-04 12:24:36 -05:00
|
|
|
return d.tmplHandlers.Tmpl
|
2020-01-15 09:59:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
func (d *Deps) TextTmpl() tpl.TemplateParseFinder {
|
2023-01-04 12:24:36 -05:00
|
|
|
return d.tmplHandlers.TxtTmpl
|
2017-01-10 04:55:03 -05:00
|
|
|
}
|
|
|
|
|
2020-12-23 03:26:23 -05:00
|
|
|
func (d *Deps) Close() error {
|
|
|
|
return d.BuildClosers.Close()
|
|
|
|
}
|
|
|
|
|
2017-01-10 04:55:03 -05:00
|
|
|
// DepsCfg contains configuration options that can be used to configure Hugo
|
|
|
|
// on a global level, i.e. logging etc.
|
|
|
|
// Nil values will be given default values.
|
|
|
|
type DepsCfg struct {
|
2023-06-16 02:17:42 -04:00
|
|
|
// The logger to use. Only set in some tests.
|
|
|
|
// TODO(bep) get rid of this.
|
|
|
|
TestLogger loggers.Logger
|
|
|
|
|
|
|
|
// The logging level to use.
|
|
|
|
LogLevel logg.Level
|
2017-01-10 04:55:03 -05:00
|
|
|
|
2023-06-16 02:17:42 -04:00
|
|
|
// Where to write the logs.
|
|
|
|
// Currently we typically write everything to stdout.
|
|
|
|
LogOut io.Writer
|
2017-01-10 04:55:03 -05:00
|
|
|
|
|
|
|
// The file systems to use
|
|
|
|
Fs *hugofs.Fs
|
|
|
|
|
2018-11-26 04:11:22 -05:00
|
|
|
// The Site in use
|
2019-01-02 06:33:26 -05:00
|
|
|
Site page.Site
|
2018-11-26 04:11:22 -05:00
|
|
|
|
2023-01-04 12:24:36 -05:00
|
|
|
Configs *allconfig.Configs
|
2018-08-05 05:13:49 -04:00
|
|
|
|
2017-01-10 04:55:03 -05:00
|
|
|
// Template handling.
|
2017-02-04 22:20:06 -05:00
|
|
|
TemplateProvider ResourceProvider
|
|
|
|
|
|
|
|
// i18n handling.
|
|
|
|
TranslationProvider ResourceProvider
|
2017-01-10 04:55:03 -05:00
|
|
|
}
|
2020-01-15 09:59:56 -05:00
|
|
|
|
2023-01-04 12:24:36 -05:00
|
|
|
// BuildState are state used during a build.
|
2020-02-25 15:40:02 -05:00
|
|
|
type BuildState struct {
|
|
|
|
counter uint64
|
2023-01-04 12:24:36 -05:00
|
|
|
|
|
|
|
mu sync.Mutex // protects state below.
|
|
|
|
|
|
|
|
// A set of ilenames in /public that
|
|
|
|
// contains a post-processing prefix.
|
|
|
|
filenamesWithPostPrefix map[string]bool
|
2020-01-15 09:59:56 -05:00
|
|
|
}
|
|
|
|
|
2023-01-04 12:24:36 -05:00
|
|
|
func (b *BuildState) AddFilenameWithPostPrefix(filename string) {
|
|
|
|
b.mu.Lock()
|
|
|
|
defer b.mu.Unlock()
|
|
|
|
if b.filenamesWithPostPrefix == nil {
|
|
|
|
b.filenamesWithPostPrefix = make(map[string]bool)
|
|
|
|
}
|
|
|
|
b.filenamesWithPostPrefix[filename] = true
|
2020-02-25 15:40:02 -05:00
|
|
|
}
|
|
|
|
|
2023-01-04 12:24:36 -05:00
|
|
|
func (b *BuildState) GetFilenamesWithPostPrefix() []string {
|
|
|
|
b.mu.Lock()
|
|
|
|
defer b.mu.Unlock()
|
|
|
|
var filenames []string
|
|
|
|
for filename := range b.filenamesWithPostPrefix {
|
|
|
|
filenames = append(filenames, filename)
|
|
|
|
}
|
|
|
|
sort.Strings(filenames)
|
|
|
|
return filenames
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *BuildState) Incr() int {
|
|
|
|
return int(atomic.AddUint64(&b.counter, uint64(1)))
|
2020-01-15 09:59:56 -05:00
|
|
|
}
|
2020-12-23 03:26:23 -05:00
|
|
|
|
|
|
|
type Closer interface {
|
|
|
|
Close() error
|
|
|
|
}
|
|
|
|
|
|
|
|
type Closers struct {
|
|
|
|
mu sync.Mutex
|
|
|
|
cs []Closer
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cs *Closers) Add(c Closer) {
|
|
|
|
cs.mu.Lock()
|
|
|
|
defer cs.mu.Unlock()
|
|
|
|
cs.cs = append(cs.cs, c)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cs *Closers) Close() error {
|
|
|
|
cs.mu.Lock()
|
|
|
|
defer cs.mu.Unlock()
|
|
|
|
for _, c := range cs.cs {
|
|
|
|
c.Close()
|
|
|
|
}
|
|
|
|
|
|
|
|
cs.cs = cs.cs[:0]
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|