diff options
-rw-r--r-- | README.md | 170 | ||||
-rw-r--r-- | commands/hugobuilder.go | 108 | ||||
-rw-r--r-- | commands/mod.go | 5 | ||||
-rw-r--r-- | commands/server.go | 16 | ||||
-rw-r--r-- | create/skeletons/theme/hugo.toml | 2 | ||||
-rw-r--r-- | docs/content/en/methods/page/GitInfo.md | 10 | ||||
-rw-r--r-- | go.mod | 3 | ||||
-rw-r--r-- | go.sum | 6 | ||||
-rw-r--r-- | hugofs/hashing_fs.go | 32 | ||||
-rw-r--r-- | hugofs/hashing_fs_test.go | 35 | ||||
-rw-r--r-- | hugolib/content_map_page.go | 4 | ||||
-rw-r--r-- | hugolib/dates_test.go | 83 | ||||
-rw-r--r-- | hugolib/pagecollections.go | 9 | ||||
-rw-r--r-- | hugolib/pagecollections_test.go | 29 | ||||
-rw-r--r-- | hugoreleaser.env | 6 | ||||
-rw-r--r-- | resources/page/pagemeta/page_frontmatter.go | 6 | ||||
-rw-r--r-- | source/fileInfo.go | 2 | ||||
-rw-r--r-- | tpl/crypto/crypto.go | 2 | ||||
-rw-r--r-- | tpl/crypto/init.go | 7 | ||||
-rw-r--r-- | tpl/hash/hash.go | 93 | ||||
-rw-r--r-- | tpl/hash/hash_test.go | 84 | ||||
-rw-r--r-- | tpl/tplimpl/template_funcs.go | 1 |
22 files changed, 536 insertions, 177 deletions
@@ -5,6 +5,7 @@ [documentation repository]: https://github.com/gohugoio/hugoDocs [documentation]: https://gohugo.io/documentation [dragonfly bsd, freebsd, netbsd, and openbsd]: https://gohugo.io/installation/bsd +[features]: https://gohugo.io/about/features/ [forum]: https://discourse.gohugo.io [friends]: https://github.com/gohugoio/hugo/graphs/contributors [go]: https://go.dev/ @@ -19,7 +20,6 @@ [static site generator]: https://en.wikipedia.org/wiki/Static_site_generator [support]: https://discourse.gohugo.io [themes]: https://themes.gohugo.io/ -[twitter]: https://twitter.com/gohugoio [website]: https://gohugo.io [windows]: https://gohugo.io/installation/windows @@ -33,7 +33,7 @@ A fast and flexible static site generator built with love by [bep], [spf13], and [![Tests on Linux, MacOS and Windows](https://github.com/gohugoio/hugo/workflows/Test/badge.svg)](https://github.com/gohugoio/hugo/actions?query=workflow%3ATest) [![Go Report Card](https://goreportcard.com/badge/github.com/gohugoio/hugo)](https://goreportcard.com/report/github.com/gohugoio/hugo) -[Website] | [Installation] | [Documentation] | [Support] | [Contributing] | <a rel="me" href="https://fosstodon.org/@gohugoio">Mastodon</a> +[Website] | [Installation] | [Documentation] | [Support] | [Contributing] | <a rel="me" href="https://fosstodon.org/@gohugoio">Mastodon</a> | <a rel="me" href="https://x.com/gohugoiov2">X</a> ## Overview @@ -52,12 +52,15 @@ Use Hugo's embedded web server during development to instantly see changes to co Hugo's fast asset pipelines include: -- CSS bundling – transpilation (Sass), tree shaking, minification, source maps, SRI hashing, and PostCSS integration -- JavaScript bundling – transpilation (TypeScript, JSX), tree shaking, minification, source maps, and SRI hashing -- Image processing – convert, resize, crop, rotate, adjust colors, apply filters, overlay text and images, and extract EXIF data +- Image processing – Convert, resize, crop, rotate, adjust colors, apply filters, overlay text and images, and extract EXIF data +- JavaScript bundling – Transpile TypeScript and JSX to JavaScript, bundle, tree shake, minify, create source maps, and perform SRI hashing. +- Sass processing – Transpile Sass to CSS, bundle, tree shake, minify, create source maps, perform SRI hashing, and integrate with PostCSS +- Tailwind CSS processing – Compile Tailwind CSS utility classes into standard CSS, bundle, tree shake, optimize, minify, perform SRI hashing, and integrate with PostCSS And with [Hugo Modules], you can share content, assets, data, translations, themes, templates, and configuration with other projects via public or private Git repositories. +See the [features] section of the documentation for a comprehensive summary of Hugo's capabilities. + ## Sponsors <p> </p> @@ -143,40 +146,39 @@ Hugo stands on the shoulders of great open source libraries. Run `hugo env --log ```text cloud.google.com/go/compute/metadata="v0.2.3" -cloud.google.com/go/iam="v1.1.3" -cloud.google.com/go/storage="v1.31.0" -cloud.google.com/go="v0.110.8" -github.com/Azure/azure-sdk-for-go/sdk/azcore="v1.7.0" -github.com/Azure/azure-sdk-for-go/sdk/azidentity="v1.3.0" -github.com/Azure/azure-sdk-for-go/sdk/internal="v1.3.0" -github.com/Azure/azure-sdk-for-go/sdk/storage/azblob="v1.1.0" +cloud.google.com/go/iam="v1.1.5" +cloud.google.com/go/storage="v1.35.1" +cloud.google.com/go="v0.110.10" +github.com/Azure/azure-sdk-for-go/sdk/azcore="v1.9.0" +github.com/Azure/azure-sdk-for-go/sdk/azidentity="v1.4.0" +github.com/Azure/azure-sdk-for-go/sdk/internal="v1.5.0" +github.com/Azure/azure-sdk-for-go/sdk/storage/azblob="v1.2.0" github.com/Azure/go-autorest/autorest/to="v0.4.0" -github.com/AzureAD/microsoft-authentication-library-for-go="v1.0.0" +github.com/AzureAD/microsoft-authentication-library-for-go="v1.2.0" github.com/BurntSushi/locker="v0.0.0-20171006230638-a6e239ea1c69" -github.com/PuerkitoBio/purell="v1.1.1" -github.com/PuerkitoBio/urlesc="v0.0.0-20170810143723-de5bf2ad4578" -github.com/alecthomas/chroma/v2="v2.11.1" -github.com/armon/go-radix="v1.0.0" -github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream="v1.4.11" -github.com/aws/aws-sdk-go-v2/config="v1.18.32" -github.com/aws/aws-sdk-go-v2/credentials="v1.13.31" -github.com/aws/aws-sdk-go-v2/feature/ec2/imds="v1.13.7" -github.com/aws/aws-sdk-go-v2/feature/s3/manager="v1.11.76" -github.com/aws/aws-sdk-go-v2/internal/configsources="v1.1.37" -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2="v2.4.31" -github.com/aws/aws-sdk-go-v2/internal/ini="v1.3.38" -github.com/aws/aws-sdk-go-v2/internal/v4a="v1.1.0" -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding="v1.9.12" -github.com/aws/aws-sdk-go-v2/service/internal/checksum="v1.1.32" -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url="v1.9.31" -github.com/aws/aws-sdk-go-v2/service/internal/s3shared="v1.15.0" -github.com/aws/aws-sdk-go-v2/service/s3="v1.38.1" -github.com/aws/aws-sdk-go-v2/service/sso="v1.13.1" -github.com/aws/aws-sdk-go-v2/service/ssooidc="v1.15.1" -github.com/aws/aws-sdk-go-v2/service/sts="v1.21.1" -github.com/aws/aws-sdk-go-v2="v1.20.0" -github.com/aws/aws-sdk-go="v1.48.2" -github.com/aws/smithy-go="v1.14.0" +github.com/alecthomas/chroma/v2="v2.14.0" +github.com/armon/go-radix="v1.0.1-0.20221118154546-54df44f2176c" +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream="v1.5.4" +github.com/aws/aws-sdk-go-v2/config="v1.26.1" +github.com/aws/aws-sdk-go-v2/credentials="v1.16.12" +github.com/aws/aws-sdk-go-v2/feature/ec2/imds="v1.14.10" +github.com/aws/aws-sdk-go-v2/feature/s3/manager="v1.15.7" +github.com/aws/aws-sdk-go-v2/internal/configsources="v1.3.5" +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2="v2.6.5" +github.com/aws/aws-sdk-go-v2/internal/ini="v1.7.2" +github.com/aws/aws-sdk-go-v2/internal/v4a="v1.2.9" +github.com/aws/aws-sdk-go-v2/service/cloudfront="v1.35.4" +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding="v1.10.4" +github.com/aws/aws-sdk-go-v2/service/internal/checksum="v1.2.9" +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url="v1.10.9" +github.com/aws/aws-sdk-go-v2/service/internal/s3shared="v1.16.9" +github.com/aws/aws-sdk-go-v2/service/s3="v1.47.5" +github.com/aws/aws-sdk-go-v2/service/sso="v1.18.5" +github.com/aws/aws-sdk-go-v2/service/ssooidc="v1.21.5" +github.com/aws/aws-sdk-go-v2/service/sts="v1.26.5" +github.com/aws/aws-sdk-go-v2="v1.26.1" +github.com/aws/aws-sdk-go="v1.50.7" +github.com/aws/smithy-go="v1.20.2" github.com/bep/clocks="v0.5.0" github.com/bep/debounce="v1.2.0" github.com/bep/gitmap="v1.1.2" @@ -185,32 +187,35 @@ github.com/bep/godartsass/v2="v2.0.0" github.com/bep/godartsass="v1.2.0" github.com/bep/golibsass="v1.1.1" github.com/bep/gowebp="v0.3.0" -github.com/bep/lazycache="v0.2.0" -github.com/bep/logg="v0.3.0" +github.com/bep/lazycache="v0.4.0" +github.com/bep/logg="v0.4.0" github.com/bep/mclib="v1.20400.20402" -github.com/bep/overlayfs="v0.6.0" -github.com/bep/simplecobra="v0.3.2" +github.com/bep/overlayfs="v0.9.2" +github.com/bep/simplecobra="v0.4.0" github.com/bep/tmc="v0.5.1" github.com/clbanning/mxj/v2="v2.7.0" github.com/cli/safeexec="v1.0.1" -github.com/cpuguy83/go-md2man/v2="v2.0.2" +github.com/cpuguy83/go-md2man/v2="v2.0.3" github.com/disintegration/gift="v1.2.1" -github.com/dlclark/regexp2="v1.10.0" +github.com/dlclark/regexp2="v1.11.0" github.com/dustin/go-humanize="v1.0.1" -github.com/evanw/esbuild="v0.19.7" +github.com/evanw/esbuild="v0.21.4" github.com/fatih/color="v1.16.0" github.com/frankban/quicktest="v1.14.6" github.com/fsnotify/fsnotify="v1.7.0" -github.com/getkin/kin-openapi="v0.120.0" +github.com/getkin/kin-openapi="v0.123.0" github.com/ghodss/yaml="v1.0.0" -github.com/go-openapi/jsonpointer="v0.19.6" -github.com/go-openapi/swag="v0.22.4" +github.com/go-openapi/jsonpointer="v0.20.2" +github.com/go-openapi/swag="v0.22.8" github.com/gobuffalo/flect="v1.0.2" github.com/gobwas/glob="v0.2.3" github.com/gohugoio/go-i18n/v2="v2.1.3-0.20230805085216-e63c13218d0e" +github.com/gohugoio/httpcache="v0.7.0" +github.com/gohugoio/hugo-goldmark-extensions/extras="v0.2.0" +github.com/gohugoio/hugo-goldmark-extensions/passthrough="v0.2.0" github.com/gohugoio/locales="v0.14.0" github.com/gohugoio/localescompressed="v1.0.1" -github.com/golang-jwt/jwt/v4="v4.5.0" +github.com/golang-jwt/jwt/v5="v5.1.0" github.com/golang/groupcache="v0.0.0-20210331224755-41bb18bfe9da" github.com/golang/protobuf="v1.5.3" github.com/google/go-cmp="v0.6.0" @@ -221,7 +226,7 @@ github.com/googleapis/enterprise-certificate-proxy="v0.3.2" github.com/googleapis/gax-go/v2="v2.12.0" github.com/gorilla/websocket="v1.5.1" github.com/hairyhenderson/go-codeowners="v0.4.0" -github.com/hashicorp/golang-lru/v2="v2.0.1" +github.com/hashicorp/golang-lru/v2="v2.0.7" github.com/invopop/yaml="v0.2.0" github.com/jdkato/prose="v1.2.1" github.com/jmespath/go-jmespath="v0.4.0" @@ -231,63 +236,62 @@ github.com/kr/text="v0.2.0" github.com/kylelemons/godebug="v1.1.0" github.com/kyokomi/emoji/v2="v2.2.12" github.com/mailru/easyjson="v0.7.7" +github.com/makeworld-the-better-one/dither/v2="v2.4.0" github.com/marekm4/color-extractor="v1.2.1" github.com/mattn/go-colorable="v0.1.13" github.com/mattn/go-isatty="v0.0.20" github.com/mattn/go-runewidth="v0.0.9" github.com/mitchellh/hashstructure="v1.1.0" -github.com/mitchellh/mapstructure="v1.5.0" +github.com/mitchellh/mapstructure="v1.5.1-0.20231216201459-8508981c8b6c" github.com/mohae/deepcopy="v0.0.0-20170929034955-c48cc78d4826" github.com/muesli/smartcrop="v0.3.0" github.com/niklasfasching/go-org="v1.7.0" github.com/olekukonko/tablewriter="v0.0.5" -github.com/pelletier/go-toml/v2="v2.1.0" +github.com/pbnjay/memory="v0.0.0-20210728143218-7b4eea64cf58" +github.com/pelletier/go-toml/v2="v2.2.2" github.com/perimeterx/marshmallow="v1.1.5" github.com/pkg/browser="v0.0.0-20210911075715-681adbf594b8" github.com/pkg/errors="v0.9.1" -github.com/rogpeppe/go-internal="v1.11.0" +github.com/rogpeppe/go-internal="v1.12.0" github.com/russross/blackfriday/v2="v2.1.0" github.com/rwcarlsen/goexif="v0.0.0-20190401172101-9e8deecbddbd" -github.com/sanity-io/litter="v1.5.5" -github.com/sass/dart-sass/compiler="1.63.2" -github.com/sass/dart-sass/implementation="1.63.2" -github.com/sass/dart-sass/protocol="2.0.0" +github.com/sass/dart-sass/compiler="1.77.5" +github.com/sass/dart-sass/implementation="1.77.5" +github.com/sass/dart-sass/protocol="2.7.1" github.com/sass/libsass="3.6.5" -github.com/spf13/afero="v1.10.0" -github.com/spf13/cast="v1.5.1" -github.com/spf13/cobra="v1.7.0" -github.com/spf13/fsync="v0.9.0" +github.com/spf13/afero="v1.11.0" +github.com/spf13/cast="v1.6.0" +github.com/spf13/cobra="v1.8.0" +github.com/spf13/fsync="v0.10.1" github.com/spf13/pflag="v1.0.5" -github.com/tdewolff/minify/v2="v2.20.7" -github.com/tdewolff/parse/v2="v2.7.5" +github.com/tdewolff/minify/v2="v2.20.20" +github.com/tdewolff/parse/v2="v2.7.13" github.com/webmproject/libwebp="v1.3.2" -github.com/yuin/goldmark-emoji="v1.0.2" -github.com/yuin/goldmark="v1.6.0" +github.com/yuin/goldmark-emoji="v1.0.3" +github.com/yuin/goldmark="v1.7.4" go.opencensus.io="v0.24.0" -go.uber.org/atomic="v1.11.0" go.uber.org/automaxprocs="v1.5.3" -gocloud.dev="v0.34.0" -golang.org/x/crypto="v0.15.0" +gocloud.dev="v0.36.0" +golang.org/x/crypto="v0.23.0" golang.org/x/exp="v0.0.0-20221031165847-c99f073a8326" -golang.org/x/image="v0.13.0" -golang.org/x/mod="v0.14.0" -golang.org/x/net="v0.18.0" -golang.org/x/oauth2="v0.13.0" -golang.org/x/sync="v0.5.0" -golang.org/x/sys="v0.14.0" -golang.org/x/text="v0.14.0" -golang.org/x/time="v0.3.0" -golang.org/x/tools="v0.15.0" -golang.org/x/xerrors="v0.0.0-20220907171357-04be3eba64a2" -google.golang.org/api="v0.151.0" -google.golang.org/genproto/googleapis/api="v0.0.0-20231016165738-49dd2c1f3d0b" -google.golang.org/genproto/googleapis/rpc="v0.0.0-20231030173426-d783a09b4405" -google.golang.org/genproto="v0.0.0-20231016165738-49dd2c1f3d0b" +golang.org/x/image="v0.16.0" +golang.org/x/mod="v0.17.0" +golang.org/x/net="v0.25.0" +golang.org/x/oauth2="v0.15.0" +golang.org/x/sync="v0.7.0" +golang.org/x/sys="v0.20.0" +golang.org/x/text="v0.15.0" +golang.org/x/time="v0.5.0" +golang.org/x/tools="v0.20.0" +golang.org/x/xerrors="v0.0.0-20231012003039-104605ab7028" +google.golang.org/api="v0.152.0" +google.golang.org/genproto/googleapis/api="v0.0.0-20231120223509-83a465c0220f" +google.golang.org/genproto/googleapis/rpc="v0.0.0-20231120223509-83a465c0220f" +google.golang.org/genproto="v0.0.0-20231120223509-83a465c0220f" google.golang.org/grpc="v1.59.0" -google.golang.org/protobuf="v1.31.0" +google.golang.org/protobuf="v1.33.0" gopkg.in/yaml.v2="v2.4.0" gopkg.in/yaml.v3="v3.0.1" -howett.net/plist="v1.0.0" software.sslmate.com/src/go-pkcs12="v0.2.0" ``` </details> diff --git a/commands/hugobuilder.go b/commands/hugobuilder.go index 1a4a61264..15373d8c6 100644 --- a/commands/hugobuilder.go +++ b/commands/hugobuilder.go @@ -744,6 +744,20 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher, staticEvents := []fsnotify.Event{} dynamicEvents := []fsnotify.Event{} + filterDuplicateEvents := func(evs []fsnotify.Event) []fsnotify.Event { + seen := make(map[string]bool) + var n int + for _, ev := range evs { + if seen[ev.Name] { + continue + } + seen[ev.Name] = true + evs[n] = ev + n++ + } + return evs[:n] + } + h, err := c.hugo() if err != nil { c.r.logger.Errorln("Error getting the Hugo object:", err) @@ -833,6 +847,11 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher, } } + lrl := c.r.logger.InfoCommand("livereload") + + staticEvents = filterDuplicateEvents(staticEvents) + dynamicEvents = filterDuplicateEvents(dynamicEvents) + if len(staticEvents) > 0 { c.printChangeDetected("Static files") @@ -853,19 +872,20 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher, if c.s != nil && c.s.doLiveReload { // Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized - // force refresh when more than one file if !c.errState.wasErr() && len(staticEvents) == 1 { - ev := staticEvents[0] h, err := c.hugo() if err != nil { c.r.logger.Errorln("Error getting the Hugo object:", err) return } - path := h.BaseFs.SourceFilesystems.MakeStaticPathRelative(ev.Name) + + path := h.BaseFs.SourceFilesystems.MakeStaticPathRelative(staticEvents[0].Name) path = h.RelURL(paths.ToSlashTrimLeading(path), false) + lrl.Logf("refreshing static file %q", path) livereload.RefreshPath(path) } else { + lrl.Logf("got %d static file change events, force refresh", len(staticEvents)) livereload.ForceRefresh() } } @@ -889,43 +909,30 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher, }() if c.s != nil && c.s.doLiveReload { - if len(partitionedEvents.ContentEvents) == 0 && len(partitionedEvents.AssetEvents) > 0 { - if c.errState.wasErr() { - livereload.ForceRefresh() - return - } - changed := c.changeDetector.changed() - if c.changeDetector != nil && len(changed) == 0 { + if c.errState.wasErr() { + livereload.ForceRefresh() + return + } + + changed := c.changeDetector.changed() + if c.changeDetector != nil { + lrl.Logf("build changed %d files", len(changed)) + if len(changed) == 0 { // Nothing has changed. return - } else if len(changed) == 1 { - pathToRefresh := h.PathSpec.RelURL(paths.ToSlashTrimLeading(changed[0]), false) - livereload.RefreshPath(pathToRefresh) - } else { - livereload.ForceRefresh() - // See https://github.com/gohugoio/hugo/issues/12600. - // If this change set also contains one or more CSS files, we need to - // refresh these as well. - var cssChanges []string - var otherChanges []string - - for _, ev := range changed { - if strings.HasSuffix(ev, ".css") { - cssChanges = append(cssChanges, ev) - } else { - otherChanges = append(otherChanges, ev) - } - } + } + } - if len(otherChanges) > 0 { - livereload.ForceRefresh() - // Allow some time for the live reload script to get reconnected. - time.Sleep(200 * time.Millisecond) - } + // If this change set also contains one or more CSS files, we need to + // refresh these as well. + var cssChanges []string + var otherChanges []string - for _, ev := range cssChanges { - livereload.RefreshPath(h.PathSpec.RelURL(paths.ToSlashTrimLeading(ev), false)) - } + for _, ev := range changed { + if strings.HasSuffix(ev, ".css") { + cssChanges = append(cssChanges, ev) + } else { + otherChanges = append(otherChanges, ev) } } @@ -941,11 +948,36 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher, } } - if p != nil { - livereload.NavigateToPathForPort(p.RelPermalink(), p.Site().ServerPort()) + if p != nil && p.RelPermalink() != "" { + link, port := p.RelPermalink(), p.Site().ServerPort() + lrl.Logf("navigating to %q using port %d", link, port) + livereload.NavigateToPathForPort(link, port) } else { + lrl.Logf("no page to navigate to, force refresh") livereload.ForceRefresh() } + } else if len(otherChanges) > 0 { + if len(otherChanges) == 1 { + // Allow single changes to be refreshed without a full page reload. + pathToRefresh := h.PathSpec.RelURL(paths.ToSlashTrimLeading(otherChanges[0]), false) + lrl.Logf("refreshing %q", pathToRefresh) + livereload.RefreshPath(pathToRefresh) + } else if len(cssChanges) == 0 { + lrl.Logf("force refresh") + livereload.ForceRefresh() + } + } + + if len(cssChanges) > 0 { + // Allow some time for the live reload script to get reconnected. + if len(otherChanges) > 0 { + time.Sleep(200 * time.Millisecond) + } + for _, ev := range cssChanges { + pathToRefresh := h.PathSpec.RelURL(paths.ToSlashTrimLeading(ev), false) + lrl.Logf("refreshing CSS %q", pathToRefresh) + livereload.RefreshPath(pathToRefresh) + } } } } diff --git a/commands/mod.go b/commands/mod.go index 7ff662944..0fa83e5c0 100644 --- a/commands/mod.go +++ b/commands/mod.go @@ -268,13 +268,14 @@ Run "go help get" for more information. All flags available for "go get" is also if info.Name() == "go.mod" { // Found a module. dir := filepath.Dir(path) - r.Println("Update module in", dir) + cfg := config.New() cfg.Set("workingDir", dir) - conf, err := r.ConfigFromProvider(r.configVersionID.Load(), flagsToCfg(cd, cfg)) + conf, err := r.ConfigFromProvider(r.configVersionID.Add(1), flagsToCfg(cd, cfg)) if err != nil { return err } + r.Println("Update module in", conf.configs.Base.WorkingDir) client := conf.configs.ModulesClient return client.Get(args...) diff --git a/commands/server.go b/commands/server.go index 6d64a38c6..680c73a13 100644 --- a/commands/server.go +++ b/commands/server.go @@ -162,16 +162,16 @@ type dynamicEvents struct { type fileChangeDetector struct { sync.Mutex - current map[string]string - prev map[string]string + current map[string]uint64 + prev map[string]uint64 irrelevantRe *regexp.Regexp } -func (f *fileChangeDetector) OnFileClose(name, md5sum string) { +func (f *fileChangeDetector) OnFileClose(name string, checksum uint64) { f.Lock() defer f.Unlock() - f.current[name] = md5sum + f.current[name] = checksum } func (f *fileChangeDetector) PrepareNew() { @@ -183,16 +183,16 @@ func (f *fileChangeDetector) PrepareNew() { defer f.Unlock() if f.current == nil { - f.current = make(map[string]string) - f.prev = make(map[string]string) + f.current = make(map[string]uint64) + f.prev = make(map[string]uint64) return } - f.prev = make(map[string]string) + f.prev = make(map[string]uint64) for k, v := range f.current { f.prev[k] = v } - f.current = make(map[string]string) + f.current = make(map[string]uint64) } func (f *fileChangeDetector) changed() []string { diff --git a/create/skeletons/theme/hugo.toml b/create/skeletons/theme/hugo.toml index 890e58deb..6c35bc476 100644 --- a/create/skeletons/theme/hugo.toml +++ b/create/skeletons/theme/hugo.toml @@ -1,5 +1,5 @@ baseURL = 'https://example.org/' -languageCode = 'en-us' +languageCode = 'en-US' title = 'My New Hugo Site' [[menus.main]] diff --git a/docs/content/en/methods/page/GitInfo.md b/docs/content/en/methods/page/GitInfo.md index 9dba2a2b2..c54a77371 100644 --- a/docs/content/en/methods/page/GitInfo.md +++ b/docs/content/en/methods/page/GitInfo.md @@ -113,6 +113,16 @@ This is configurable. See [details]. {{ end }} ``` +###### Body + +(`string`) The commit message body. + +```go-html-template +{{ with .GitInfo }} + {{ .Body }} → - Two new pages added. +{{ end }} +``` + ## Last modified date By default, when `enableGitInfo` is `true`, the `Lastmod` method on a `Page` object returns the Git AuthorDate of the last commit that included the file. @@ -8,7 +8,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/cloudfront v1.35.4 github.com/bep/clocks v0.5.0 github.com/bep/debounce v1.2.0 - github.com/bep/gitmap v1.1.2 + github.com/bep/gitmap v1.4.0 github.com/bep/goat v0.5.0 github.com/bep/godartsass v1.2.0 github.com/bep/godartsass/v2 v2.0.0 @@ -21,6 +21,7 @@ require ( github.com/bep/overlayfs v0.9.2 github.com/bep/simplecobra v0.4.0 github.com/bep/tmc v0.5.1 + github.com/cespare/xxhash/v2 v2.3.0 github.com/clbanning/mxj/v2 v2.7.0 github.com/cli/safeexec v1.0.1 github.com/disintegration/gift v1.2.1 @@ -118,8 +118,8 @@ github.com/bep/clocks v0.5.0 h1:hhvKVGLPQWRVsBP/UB7ErrHYIO42gINVbvqxvYTPVps= github.com/bep/clocks v0.5.0/go.mod h1:SUq3q+OOq41y2lRQqH5fsOoxN8GbxSiT6jvoVVLCVhU= github.com/bep/debounce v1.2.0 h1:wXds8Kq8qRfwAOpAxHrJDbCXgC5aHSzgQb/0gKsHQqo= github.com/bep/debounce v1.2.0/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/bep/gitmap v1.1.2 h1:zk04w1qc1COTZPPYWDQHvns3y1afOsdRfraFQ3qI840= -github.com/bep/gitmap v1.1.2/go.mod h1:g9VRETxFUXNWzMiuxOwcudo6DfZkW9jOsOW0Ft4kYaY= +github.com/bep/gitmap v1.4.0 h1:GeWbPb2QDTfcZLBQmCB693N3sJmPQfeu81fDrD5r8x8= +github.com/bep/gitmap v1.4.0/go.mod h1:n+3W1f/rot2hynsqEGxGMErPRgT41n9CkGuzPvz9cIw= github.com/bep/goat v0.5.0 h1:S8jLXHCVy/EHIoCY+btKkmcxcXFd34a0Q63/0D4TKeA= github.com/bep/goat v0.5.0/go.mod h1:Md9x7gRxiWKs85yHlVTvHQw9rg86Bm+Y4SuYE8CTH7c= github.com/bep/godartsass v1.2.0 h1:E2VvQrxAHAFwbjyOIExAMmogTItSKodoKuijNrGm5yU= @@ -147,6 +147,8 @@ github.com/bep/tmc v0.5.1/go.mod h1:tGYHN8fS85aJPhDLgXETVKp+PR382OvFi2+q2GkGsq0= github.com/bep/workers v1.0.0 h1:U+H8YmEaBCEaFZBst7GcRVEoqeRC9dzH2dWOwGmOchg= github.com/bep/workers v1.0.0/go.mod h1:7kIESOB86HfR2379pwoMWNy8B50D7r99fRLUyPSNyCs= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= diff --git a/hugofs/hashing_fs.go b/hugofs/hashing_fs.go index d15ba5863..5072e2586 100644 --- a/hugofs/hashing_fs.go +++ b/hugofs/hashing_fs.go @@ -14,25 +14,24 @@ package hugofs import ( - "crypto/md5" - "encoding/hex" "hash" "os" + "github.com/cespare/xxhash/v2" "github.com/spf13/afero" ) var ( - _ afero.Fs = (*md5HashingFs)(nil) - _ FilesystemUnwrapper = (*md5HashingFs)(nil) + _ afero.Fs = (*hashingFs)(nil) + _ FilesystemUnwrapper = (*hashingFs)(nil) ) // FileHashReceiver will receive the filename an the content's MD5 sum on file close. type FileHashReceiver interface { - OnFileClose(name, md5sum string) + OnFileClose(name string, checksum uint64) } -type md5HashingFs struct { +type hashingFs struct { afero.Fs hashReceiver FileHashReceiver } @@ -45,14 +44,14 @@ type md5HashingFs struct { // Note that this will only work for file operations that use the io.Writer // to write content to file, but that is fine for the "publish content" use case. func NewHashingFs(delegate afero.Fs, hashReceiver FileHashReceiver) afero.Fs { - return &md5HashingFs{Fs: delegate, hashReceiver: hashReceiver} + return &hashingFs{Fs: delegate, hashReceiver: hashReceiver} } -func (fs *md5HashingFs) UnwrapFilesystem() afero.Fs { +func (fs *hashingFs) UnwrapFilesystem() afero.Fs { return fs.Fs } -func (fs *md5HashingFs) Create(name string) (afero.File, error) { +func (fs *hashingFs) Create(name string) (afero.File, error) { f, err := fs.Fs.Create(name) if err == nil { f = fs.wrapFile(f) @@ -60,7 +59,7 @@ func (fs *md5HashingFs) Create(name string) (afero.File, error) { return f, err } -func (fs *md5HashingFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) { +func (fs *hashingFs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) { f, err := fs.Fs.OpenFile(name, flag, perm) if err == nil && isWrite(flag) { f = fs.wrapFile(f) @@ -68,17 +67,17 @@ func (fs *md5HashingFs) OpenFile(name string, flag int, perm os.FileMode) (afero return f, err } -func (fs *md5HashingFs) wrapFile(f afero.File) afero.File { - return &hashingFile{File: f, h: md5.New(), hashReceiver: fs.hashReceiver} +func (fs *hashingFs) wrapFile(f afero.File) afero.File { + return &hashingFile{File: f, h: xxhash.New(), hashReceiver: fs.hashReceiver} } -func (fs *md5HashingFs) Name() string { - return "md5HashingFs" +func (fs *hashingFs) Name() string { + return "hashingFs" } type hashingFile struct { hashReceiver FileHashReceiver - h hash.Hash + h hash.Hash64 afero.File } @@ -91,7 +90,6 @@ func (h *hashingFile) Write(p []byte) (n int, err error) { } func (h *hashingFile) Close() error { - sum := hex.EncodeToString(h.h.Sum(nil)) - h.hashReceiver.OnFileClose(h.Name(), sum) + h.hashReceiver.OnFileClose(h.Name(), h.h.Sum64()) return h.File.Close() } diff --git a/hugofs/hashing_fs_test.go b/hugofs/hashing_fs_test.go index 3e1f6c41d..74781ba8d 100644 --- a/hugofs/hashing_fs_test.go +++ b/hugofs/hashing_fs_test.go @@ -14,6 +14,8 @@ |