mirror of
https://github.com/gohugoio/hugo.git
synced 2026-09-02 11:42:37 +00:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ace564e362 | |||
| bf7ee8a91a | |||
| d912491f2d | |||
| 857374e693 | |||
| c27639b9a0 | |||
| ceb486f98c | |||
| 5afc89f2bf | |||
| c1eac616d5 | |||
| 3c8256a137 | |||
| 19d76ae96b | |||
| 11ecea6106 | |||
| da98724bc8 | |||
| 4d470bb732 | |||
| 0ff8e13c1c | |||
| ffd37d4f75 | |||
| b4b65245b2 |
@@ -104,3 +104,10 @@ jobs:
|
||||
- name: Build tags
|
||||
run: |
|
||||
go install -tags extended,nodeploy
|
||||
- if: matrix.os == 'ubuntu-latest'
|
||||
name: Build for dragonfly
|
||||
run: |
|
||||
go install
|
||||
env:
|
||||
GOARCH: amd64
|
||||
GOOS: dragonfly
|
||||
|
||||
@@ -63,7 +63,7 @@ And with [Hugo Modules], you can share content, assets, data, translations, them
|
||||
<p> </p>
|
||||
<p float="left">
|
||||
<a href="https://www.linode.com/?utm_campaign=hugosponsor&utm_medium=banner&utm_source=hugogithub" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/linode-logo_standard_light_medium.png" width="200" alt="Linode"></a>
|
||||
<a href="https://cloudcannon.com/?utm_campaign=HugoSponsorship&utm_source=sponsor&utm_content=gohugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/cloudcannon-blue.svg" width="220" alt="CloudCannon"></a>
|
||||
<a href="https://cloudcannon.com/hugo-cms/?utm_campaign=HugoSponsorship&utm_source=sponsor&utm_content=gohugo" target="_blank"><img src="https://raw.githubusercontent.com/gohugoio/gohugoioTheme/master/assets/images/sponsors/cloudcannon-blue.svg" width="220" alt="CloudCannon"></a>
|
||||
<p> </p>
|
||||
|
||||
## Installation
|
||||
@@ -176,7 +176,6 @@ github.com/aws/aws-sdk-go-v2/service/sts="v1.19.2"
|
||||
github.com/aws/aws-sdk-go-v2="v1.18.1"
|
||||
github.com/aws/aws-sdk-go="v1.44.284"
|
||||
github.com/aws/smithy-go="v1.13.5"
|
||||
github.com/bep/clock="v0.3.0"
|
||||
github.com/bep/clocks="v0.5.0"
|
||||
github.com/bep/debounce="v1.2.0"
|
||||
github.com/bep/gitmap="v1.1.2"
|
||||
|
||||
+10
-12
@@ -30,7 +30,7 @@ import (
|
||||
|
||||
"go.uber.org/automaxprocs/maxprocs"
|
||||
|
||||
"github.com/bep/clock"
|
||||
"github.com/bep/clocks"
|
||||
"github.com/bep/lazycache"
|
||||
"github.com/bep/logg"
|
||||
"github.com/bep/overlayfs"
|
||||
@@ -110,12 +110,10 @@ type rootCommand struct {
|
||||
environment string
|
||||
|
||||
// Common build flags.
|
||||
baseURL string
|
||||
gc bool
|
||||
poll string
|
||||
forceSyncStatic bool
|
||||
printPathWarnings bool
|
||||
printUnusedTemplates bool
|
||||
baseURL string
|
||||
gc bool
|
||||
poll string
|
||||
forceSyncStatic bool
|
||||
|
||||
// Profile flags (for debugging of performance problems)
|
||||
cpuprofile string
|
||||
@@ -175,7 +173,7 @@ func (r *rootCommand) ConfigFromConfig(key int32, oldConf *commonConfig) (*commo
|
||||
|
||||
if !configs.Base.C.Clock.IsZero() {
|
||||
// TODO(bep) find a better place for this.
|
||||
htime.Clock = clock.Start(configs.Base.C.Clock)
|
||||
htime.Clock = clocks.Start(configs.Base.C.Clock)
|
||||
}
|
||||
|
||||
return &commonConfig{
|
||||
@@ -285,10 +283,10 @@ func (r *rootCommand) ConfigFromProvider(key int32, cfg config.Provider) (*commo
|
||||
|
||||
if !base.C.Clock.IsZero() {
|
||||
// TODO(bep) find a better place for this.
|
||||
htime.Clock = clock.Start(configs.Base.C.Clock)
|
||||
htime.Clock = clocks.Start(configs.Base.C.Clock)
|
||||
}
|
||||
|
||||
if base.LogPathWarnings {
|
||||
if base.PrintPathWarnings {
|
||||
// Note that we only care about the "dynamic creates" here,
|
||||
// so skip the static fs.
|
||||
fs.PublishDir = hugofs.NewCreateCountingFs(fs.PublishDir)
|
||||
@@ -544,8 +542,8 @@ func applyLocalFlagsBuild(cmd *cobra.Command, r *rootCommand) {
|
||||
cmd.Flags().BoolP("noChmod", "", false, "don't sync permission mode of files")
|
||||
cmd.Flags().BoolP("noBuildLock", "", false, "don't create .hugo_build.lock file")
|
||||
cmd.Flags().BoolP("printI18nWarnings", "", false, "print missing translations")
|
||||
cmd.Flags().BoolVarP(&r.printPathWarnings, "printPathWarnings", "", false, "print warnings on duplicate target paths etc.")
|
||||
cmd.Flags().BoolVarP(&r.printUnusedTemplates, "printUnusedTemplates", "", false, "print warnings on unused templates.")
|
||||
cmd.Flags().BoolP("printPathWarnings", "", false, "print warnings on duplicate target paths etc.")
|
||||
cmd.Flags().BoolP("printUnusedTemplates", "", false, "print warnings on unused templates.")
|
||||
cmd.Flags().StringVarP(&r.cpuprofile, "profile-cpu", "", "", "write cpu profile to `file`")
|
||||
cmd.Flags().StringVarP(&r.memprofile, "profile-mem", "", "", "write memory profile to `file`")
|
||||
cmd.Flags().BoolVarP(&r.printm, "printMemoryUsage", "", false, "print memory usage to screen at intervals")
|
||||
|
||||
+3
-5
@@ -79,11 +79,9 @@ func flagsToCfgWithAdditionalConfigBase(cd *simplecobra.Commandeer, cfg config.P
|
||||
|
||||
// Flags with a different name in the config.
|
||||
keyMap := map[string]string{
|
||||
"minify": "minifyOutput",
|
||||
"destination": "publishDir",
|
||||
"printI18nWarnings": "logI18nWarnings",
|
||||
"printPathWarnings": "logPathWarnings",
|
||||
"editor": "newContentEditor",
|
||||
"minify": "minifyOutput",
|
||||
"destination": "publishDir",
|
||||
"editor": "newContentEditor",
|
||||
}
|
||||
|
||||
// Flags that we for some reason don't want to expose in the site config.
|
||||
|
||||
@@ -43,7 +43,6 @@ import (
|
||||
"github.com/gohugoio/hugo/hugolib/filesystems"
|
||||
"github.com/gohugoio/hugo/livereload"
|
||||
"github.com/gohugoio/hugo/resources/page"
|
||||
"github.com/gohugoio/hugo/tpl"
|
||||
"github.com/gohugoio/hugo/watcher"
|
||||
"github.com/spf13/fsync"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -418,13 +417,6 @@ func (c *hugoBuilder) build() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.r.printUnusedTemplates {
|
||||
unusedTemplates := h.Tmpl().(tpl.UnusedTemplatesProvider).UnusedTemplates()
|
||||
for _, unusedTemplate := range unusedTemplates {
|
||||
c.r.logger.Warnf("Template %s is unused, source file %s", unusedTemplate.Name(), unusedTemplate.Filename())
|
||||
}
|
||||
}
|
||||
|
||||
h.PrintProcessingStats(os.Stdout)
|
||||
c.r.Println()
|
||||
}
|
||||
|
||||
+1
-1
@@ -224,7 +224,7 @@ Run "go help get" for more information. All flags available for "go get" is also
|
||||
run: func(ctx context.Context, cd *simplecobra.Commandeer, r *rootCommand, args []string) error {
|
||||
// We currently just pass on the flags we get to Go and
|
||||
// need to do the flag handling manually.
|
||||
if len(args) == 1 && args[0] == "-h" || args[0] == "--help" {
|
||||
if len(args) == 1 && (args[0] == "-h" || args[0] == "--help") {
|
||||
return errHelp
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bep/clock"
|
||||
"github.com/bep/clocks"
|
||||
"github.com/spf13/cast"
|
||||
|
||||
"github.com/gohugoio/locales"
|
||||
@@ -75,7 +75,7 @@ var (
|
||||
"December",
|
||||
}
|
||||
|
||||
Clock = clock.System()
|
||||
Clock = clocks.System()
|
||||
)
|
||||
|
||||
func NewTimeFormatter(ltr locales.Translator) TimeFormatter {
|
||||
|
||||
@@ -484,12 +484,6 @@ type RootConfig struct {
|
||||
// Enable to print greppable placeholders (on the form "[i18n] TRANSLATIONID") for missing translation strings.
|
||||
EnableMissingTranslationPlaceholders bool
|
||||
|
||||
// Enable to print warnings for missing translation strings.
|
||||
LogI18nWarnings bool
|
||||
|
||||
// ENable to print warnings for multiple files published to the same destination.
|
||||
LogPathWarnings bool
|
||||
|
||||
// Enable to panic on warning log entries. This may make it easier to detect the source.
|
||||
PanicOnWarning bool
|
||||
|
||||
@@ -525,6 +519,12 @@ type RootConfig struct {
|
||||
// Whether to track and print unused templates during the build.
|
||||
PrintUnusedTemplates bool
|
||||
|
||||
// Enable to print warnings for missing translation strings.
|
||||
PrintI18nWarnings bool
|
||||
|
||||
// ENable to print warnings for multiple files published to the same destination.
|
||||
PrintPathWarnings bool
|
||||
|
||||
// URL to be used as a placeholder when a page reference cannot be found in ref or relref. Is used as-is.
|
||||
RefLinksNotFoundURL string
|
||||
|
||||
|
||||
@@ -199,8 +199,8 @@ func (c ConfigLanguage) EnableMissingTranslationPlaceholders() bool {
|
||||
return c.config.EnableMissingTranslationPlaceholders
|
||||
}
|
||||
|
||||
func (c ConfigLanguage) LogI18nWarnings() bool {
|
||||
return c.config.LogI18nWarnings
|
||||
func (c ConfigLanguage) PrintI18nWarnings() bool {
|
||||
return c.config.PrintI18nWarnings
|
||||
}
|
||||
|
||||
func (c ConfigLanguage) CreateTitle(s string) string {
|
||||
|
||||
@@ -69,3 +69,21 @@ Title: {{ .Title }}
|
||||
b.Assert(modConf.Mounts[1].Lang, qt.Equals, "sv")
|
||||
|
||||
}
|
||||
|
||||
func TestConfigAliases(t *testing.T) {
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
baseURL = "https://example.com"
|
||||
logI18nWarnings = true
|
||||
logPathWarnings = true
|
||||
`
|
||||
b := hugolib.NewIntegrationTestBuilder(
|
||||
hugolib.IntegrationTestConfig{T: t, TxtarString: files},
|
||||
).Build()
|
||||
|
||||
conf := b.H.Configs.Base
|
||||
|
||||
b.Assert(conf.PrintI18nWarnings, qt.Equals, true)
|
||||
b.Assert(conf.PrintPathWarnings, qt.Equals, true)
|
||||
}
|
||||
|
||||
@@ -139,7 +139,11 @@ type configLoader struct {
|
||||
|
||||
// Handle some legacy values.
|
||||
func (l configLoader) applyConfigAliases() error {
|
||||
aliases := []types.KeyValueStr{{Key: "taxonomies", Value: "indexes"}}
|
||||
aliases := []types.KeyValueStr{
|
||||
{Key: "indexes", Value: "taxonomies"},
|
||||
{Key: "logI18nWarnings", Value: "printI18nWarnings"},
|
||||
{Key: "logPathWarnings", Value: "printPathWarnings"},
|
||||
}
|
||||
|
||||
for _, alias := range aliases {
|
||||
if l.cfg.IsSet(alias.Key) {
|
||||
|
||||
+27
-3
@@ -82,7 +82,7 @@ type LoadConfigResult struct {
|
||||
|
||||
var defaultBuild = BuildConfig{
|
||||
UseResourceCacheWhen: "fallback",
|
||||
WriteStats: false,
|
||||
BuildStats: BuildStats{},
|
||||
|
||||
CacheBusters: []CacheBuster{
|
||||
{
|
||||
@@ -111,7 +111,8 @@ type BuildConfig struct {
|
||||
|
||||
// When enabled, will collect and write a hugo_stats.json with some build
|
||||
// related aggregated data (e.g. CSS class names).
|
||||
WriteStats bool
|
||||
// Note that this was a bool <= v0.115.0.
|
||||
BuildStats BuildStats
|
||||
|
||||
// Can be used to toggle off writing of the IntelliSense /assets/jsconfig.js
|
||||
// file.
|
||||
@@ -121,6 +122,21 @@ type BuildConfig struct {
|
||||
CacheBusters []CacheBuster
|
||||
}
|
||||
|
||||
// BuildStats configures if and what to write to the hugo_stats.json file.
|
||||
type BuildStats struct {
|
||||
Enable bool
|
||||
DisableTags bool
|
||||
DisableClasses bool
|
||||
DisableIDs bool
|
||||
}
|
||||
|
||||
func (w BuildStats) Enabled() bool {
|
||||
if !w.Enable {
|
||||
return false
|
||||
}
|
||||
return !w.DisableTags || !w.DisableClasses || !w.DisableIDs
|
||||
}
|
||||
|
||||
func (b BuildConfig) clone() BuildConfig {
|
||||
b.CacheBusters = append([]CacheBuster{}, b.CacheBusters...)
|
||||
return b
|
||||
@@ -171,14 +187,22 @@ func (b *BuildConfig) CompileConfig(logger loggers.Logger) error {
|
||||
|
||||
func DecodeBuildConfig(cfg Provider) BuildConfig {
|
||||
m := cfg.GetStringMap("build")
|
||||
|
||||
b := defaultBuild.clone()
|
||||
if m == nil {
|
||||
return b
|
||||
}
|
||||
|
||||
// writeStats was a bool <= v0.115.0.
|
||||
if writeStats, ok := m["writestats"]; ok {
|
||||
if bb, ok := writeStats.(bool); ok {
|
||||
m["buildstats"] = BuildStats{Enable: bb}
|
||||
}
|
||||
}
|
||||
|
||||
err := mapstructure.WeakDecode(m, &b)
|
||||
if err != nil {
|
||||
return defaultBuild
|
||||
return b
|
||||
}
|
||||
|
||||
b.UseResourceCacheWhen = strings.ToLower(b.UseResourceCacheWhen)
|
||||
|
||||
@@ -57,7 +57,7 @@ type AllProvider interface {
|
||||
EnableMissingTranslationPlaceholders() bool
|
||||
TemplateMetrics() bool
|
||||
TemplateMetricsHints() bool
|
||||
LogI18nWarnings() bool
|
||||
PrintI18nWarnings() bool
|
||||
CreateTitle(s string) string
|
||||
IgnoreFile(s string) bool
|
||||
NewContentEditor() string
|
||||
|
||||
@@ -623,7 +623,13 @@ status = 404
|
||||
|
||||
Set `titleCaseStyle` to specify the title style used by the [title](/functions/title/) template function and the automatic section titles in Hugo.
|
||||
|
||||
By default, Hugo adheres to the capitalization rules in the [Associated Press (AP) Stylebook]. Set `titleCaseStyle` to `chicago` if you would prefer to follow the [Chicago Manual of Style], or set if to `go` to use Go's convention of capitalizing every word.
|
||||
Can be one of:
|
||||
|
||||
* `ap` (default), the capitalization rules in the [Associated Press (AP) Stylebook]
|
||||
* `chicago`, the [Chicago Manual of Style]
|
||||
* `go`, Go's convention of capitalizing every word.
|
||||
* `firstupper`, capitalize the first letter of the first word.
|
||||
* `none`, no capitalization.
|
||||
|
||||
[Associated Press (AP) Stylebook]: https://www.apstylebook.com/
|
||||
[Chicago Manual of Style]: https://www.chicagomanualofstyle.org/home.html
|
||||
|
||||
+44
-1
@@ -73,6 +73,12 @@
|
||||
"applescript"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ArangoDB AQL",
|
||||
"Aliases": [
|
||||
"aql"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Arduino",
|
||||
"Aliases": [
|
||||
@@ -85,6 +91,19 @@
|
||||
"armasm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "AutoHotkey",
|
||||
"Aliases": [
|
||||
"autohotkey",
|
||||
"ahk"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "AutoIt",
|
||||
"Aliases": [
|
||||
"autoit"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Awk",
|
||||
"Aliases": [
|
||||
@@ -666,6 +685,12 @@
|
||||
"io"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "ISCdhcpd",
|
||||
"Aliases": [
|
||||
"iscdhcpd"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "J",
|
||||
"Aliases": [
|
||||
@@ -1230,6 +1255,12 @@
|
||||
"sieve"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Smali",
|
||||
"Aliases": [
|
||||
"smali"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Smalltalk",
|
||||
"Aliases": [
|
||||
@@ -1324,6 +1355,13 @@
|
||||
"tablegen"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Tal",
|
||||
"Aliases": [
|
||||
"tal",
|
||||
"uxntal"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "TASM",
|
||||
"Aliases": [
|
||||
@@ -1505,6 +1543,12 @@
|
||||
"Name": "WDTE",
|
||||
"Aliases": null
|
||||
},
|
||||
{
|
||||
"Name": "WebGPU Shading Language",
|
||||
"Aliases": [
|
||||
"wgsl"
|
||||
]
|
||||
},
|
||||
{
|
||||
"Name": "Whiley",
|
||||
"Aliases": [
|
||||
@@ -1723,7 +1767,6 @@
|
||||
"js": {
|
||||
"precision": 0,
|
||||
"keepVarNames": false,
|
||||
"noNullishOperator": false,
|
||||
"version": 2022
|
||||
},
|
||||
"json": {
|
||||
|
||||
@@ -3,10 +3,10 @@ module github.com/gohugoio/hugo
|
||||
require (
|
||||
github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69
|
||||
github.com/PuerkitoBio/purell v1.1.1
|
||||
github.com/alecthomas/chroma/v2 v2.7.0
|
||||
github.com/alecthomas/chroma/v2 v2.8.0
|
||||
github.com/armon/go-radix v1.0.0
|
||||
github.com/aws/aws-sdk-go v1.43.5
|
||||
github.com/bep/clock v0.3.0
|
||||
github.com/bep/clocks v0.5.0
|
||||
github.com/bep/debounce v1.2.0
|
||||
github.com/bep/gitmap v1.1.2
|
||||
github.com/bep/goat v0.5.0
|
||||
@@ -25,7 +25,7 @@ require (
|
||||
github.com/cli/safeexec v1.0.1
|
||||
github.com/disintegration/gift v1.2.1
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/evanw/esbuild v0.18.10
|
||||
github.com/evanw/esbuild v0.18.11
|
||||
github.com/fatih/color v1.15.0
|
||||
github.com/fortytw2/leaktest v1.3.0
|
||||
github.com/frankban/quicktest v1.14.5
|
||||
@@ -104,7 +104,6 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.18.3 // indirect
|
||||
github.com/aws/smithy-go v1.13.5 // indirect
|
||||
github.com/bep/clocks v0.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
||||
|
||||
@@ -126,8 +126,8 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
|
||||
github.com/alecthomas/chroma/v2 v2.7.0 h1:hm1rY6c/Ob4eGclpQ7X/A3yhqBOZNUTk9q+yhyLIViI=
|
||||
github.com/alecthomas/chroma/v2 v2.7.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw=
|
||||
github.com/alecthomas/chroma/v2 v2.8.0 h1:w9WJUjFFmHHB2e8mRpL9jjy3alYDlU0QLDezj1xE264=
|
||||
github.com/alecthomas/chroma/v2 v2.8.0/go.mod h1:yrkMI9807G1ROx13fhe1v6PN2DDeaR73L3d+1nmYQtw=
|
||||
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
|
||||
@@ -174,8 +174,6 @@ github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAm
|
||||
github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8=
|
||||
github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/bep/clock v0.3.0 h1:vfOA6+wVb6pPQEiXow9f/too92vNTLe9MuwO13PfI0M=
|
||||
github.com/bep/clock v0.3.0/go.mod h1:6Gz2lapnJ9vxpvPxQ2u6FcXFRoj4kkiqQ6pm0ERZlwk=
|
||||
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=
|
||||
@@ -260,8 +258,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/evanw/esbuild v0.18.10 h1:QPpRUR5aOMQ4LQQDA9zZFpSuyT8+luBoyvPqVy8Vuv0=
|
||||
github.com/evanw/esbuild v0.18.10/go.mod h1:iINY06rn799hi48UqEnaQvVfZWe6W9bET78LbvN8VWk=
|
||||
github.com/evanw/esbuild v0.18.11 h1:Mb0qb9KyJQraob0Y7LA0DOdD8ijJs2TxhqgqrDeGq4w=
|
||||
github.com/evanw/esbuild v0.18.11/go.mod h1:iINY06rn799hi48UqEnaQvVfZWe6W9bET78LbvN8VWk=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
|
||||
|
||||
@@ -205,6 +205,8 @@ func ReaderContains(r io.Reader, subslice []byte) bool {
|
||||
// - "Go" (strings.Title)
|
||||
// - "AP" (see https://www.apstylebook.com/)
|
||||
// - "Chicago" (see http://www.chicagomanualofstyle.org/home.html)
|
||||
// - "FirstUpper" (only the first character is upper case)
|
||||
// - "None" (no transformation)
|
||||
//
|
||||
// If an unknown or empty style is provided, AP style is what you get.
|
||||
func GetTitleFunc(style string) func(s string) string {
|
||||
@@ -214,6 +216,10 @@ func GetTitleFunc(style string) func(s string) string {
|
||||
case "chicago":
|
||||
tc := transform.NewTitleConverter(transform.ChicagoStyle)
|
||||
return tc.Title
|
||||
case "none":
|
||||
return func(s string) string { return s }
|
||||
case "firstupper":
|
||||
return FirstUpper
|
||||
default:
|
||||
tc := transform.NewTitleConverter(transform.APStyle)
|
||||
return tc.Title
|
||||
|
||||
@@ -203,7 +203,7 @@ func TestReaderContains(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTitleFunc(t *testing.T) {
|
||||
title := "somewhere over the rainbow"
|
||||
title := "somewhere over the Rainbow"
|
||||
c := qt.New(t)
|
||||
|
||||
c.Assert(helpers.GetTitleFunc("go")(title), qt.Equals, "Somewhere Over The Rainbow")
|
||||
@@ -213,6 +213,8 @@ func TestGetTitleFunc(t *testing.T) {
|
||||
c.Assert(helpers.GetTitleFunc("ap")(title), qt.Equals, "Somewhere Over the Rainbow")
|
||||
c.Assert(helpers.GetTitleFunc("")(title), qt.Equals, "Somewhere Over the Rainbow")
|
||||
c.Assert(helpers.GetTitleFunc("unknown")(title), qt.Equals, "Somewhere Over the Rainbow")
|
||||
c.Assert(helpers.GetTitleFunc("none")(title), qt.Equals, title)
|
||||
c.Assert(helpers.GetTitleFunc("firstupper")(title), qt.Equals, "Somewhere over the Rainbow")
|
||||
}
|
||||
|
||||
func BenchmarkReaderContains(b *testing.B) {
|
||||
|
||||
@@ -77,6 +77,8 @@ type HugoSites struct {
|
||||
contentInit sync.Once
|
||||
content *pageMaps
|
||||
|
||||
postRenderInit sync.Once
|
||||
|
||||
// Keeps track of bundle directories and symlinks to enable partial rebuilding.
|
||||
ContentChanges *contentChangeMap
|
||||
|
||||
|
||||
+32
-13
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/langs"
|
||||
"github.com/gohugoio/hugo/publisher"
|
||||
"github.com/gohugoio/hugo/tpl"
|
||||
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
|
||||
@@ -144,18 +145,8 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
|
||||
h.SendError(fmt.Errorf("render: %w", err))
|
||||
}
|
||||
|
||||
if h.Configs.Base.LogPathWarnings {
|
||||
// We need to do this before any post processing, as that may write to the same files twice
|
||||
// and create false positives.
|
||||
hugofs.WalkFilesystems(h.Fs.PublishDir, func(fs afero.Fs) bool {
|
||||
if dfs, ok := fs.(hugofs.DuplicatesReporter); ok {
|
||||
dupes := dfs.ReportDuplicates()
|
||||
if dupes != "" {
|
||||
h.Log.Warnln("Duplicate target paths:", dupes)
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
if err := h.postRenderOnce(); err != nil {
|
||||
h.SendError(fmt.Errorf("postRenderOnce: %w", err))
|
||||
}
|
||||
|
||||
if err := h.postProcess(infol); err != nil {
|
||||
@@ -329,6 +320,34 @@ func (h *HugoSites) render(l logg.LevelLogger, config *BuildCfg) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *HugoSites) postRenderOnce() error {
|
||||
h.postRenderInit.Do(func() {
|
||||
conf := h.Configs.Base
|
||||
if conf.PrintPathWarnings {
|
||||
// We need to do this before any post processing, as that may write to the same files twice
|
||||
// and create false positives.
|
||||
hugofs.WalkFilesystems(h.Fs.PublishDir, func(fs afero.Fs) bool {
|
||||
if dfs, ok := fs.(hugofs.DuplicatesReporter); ok {
|
||||
dupes := dfs.ReportDuplicates()
|
||||
if dupes != "" {
|
||||
h.Log.Warnln("Duplicate target paths:", dupes)
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
if conf.PrintUnusedTemplates {
|
||||
unusedTemplates := h.Tmpl().(tpl.UnusedTemplatesProvider).UnusedTemplates()
|
||||
for _, unusedTemplate := range unusedTemplates {
|
||||
h.Log.Warnf("Template %s is unused, source file %s", unusedTemplate.Name(), unusedTemplate.Filename())
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *HugoSites) postProcess(l logg.LevelLogger) error {
|
||||
defer h.timeTrack(l, time.Now(), "postProcess")
|
||||
|
||||
@@ -456,7 +475,7 @@ func (h *HugoSites) writeBuildStats() error {
|
||||
if h.ResourceSpec == nil {
|
||||
panic("h.ResourceSpec is nil")
|
||||
}
|
||||
if !h.ResourceSpec.BuildConfig().WriteStats {
|
||||
if !h.ResourceSpec.BuildConfig().BuildStats.Enabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -147,6 +147,15 @@ func (s *IntegrationTestBuilder) AssertFileContent(filename string, matches ...s
|
||||
if match == "" || strings.HasPrefix(match, "#") {
|
||||
continue
|
||||
}
|
||||
var negate bool
|
||||
if strings.HasPrefix(match, "! ") {
|
||||
negate = true
|
||||
match = strings.TrimPrefix(match, "! ")
|
||||
}
|
||||
if negate {
|
||||
s.Assert(content, qt.Not(qt.Contains), match, qt.Commentf(m))
|
||||
continue
|
||||
}
|
||||
s.Assert(content, qt.Contains, match, qt.Commentf(m))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/bep/clock"
|
||||
"github.com/bep/clocks"
|
||||
"github.com/gohugoio/hugo/identity"
|
||||
"github.com/gohugoio/hugo/markup/asciidocext"
|
||||
"github.com/gohugoio/hugo/markup/rst"
|
||||
@@ -1502,8 +1502,8 @@ func TestShouldBuild(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestShouldBuildWithClock(t *testing.T) {
|
||||
htime.Clock = clock.Start(time.Date(2021, 11, 17, 20, 34, 58, 651387237, time.UTC))
|
||||
t.Cleanup(func() { htime.Clock = clock.System() })
|
||||
htime.Clock = clocks.Start(time.Date(2021, 11, 17, 20, 34, 58, 651387237, time.UTC))
|
||||
t.Cleanup(func() { htime.Clock = clocks.System() })
|
||||
past := time.Date(2009, 11, 17, 20, 34, 58, 651387237, time.UTC)
|
||||
future := time.Date(2037, 11, 17, 20, 34, 58, 651387237, time.UTC)
|
||||
zero := time.Time{}
|
||||
|
||||
@@ -1162,6 +1162,91 @@ Some text.
|
||||
}
|
||||
}
|
||||
|
||||
func TestClassCollectorConfigWriteStats(t *testing.T) {
|
||||
r := func(writeStatsConfig string) *IntegrationTestBuilder {
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
WRITE_STATS_CONFIG
|
||||
-- layouts/_default/list.html --
|
||||
<div id="myid" class="myclass">Foo</div>
|
||||
|
||||
`
|
||||
files = strings.Replace(files, "WRITE_STATS_CONFIG", writeStatsConfig, 1)
|
||||
|
||||
b := NewIntegrationTestBuilder(
|
||||
IntegrationTestConfig{
|
||||
T: t,
|
||||
TxtarString: files,
|
||||
NeedsOsFS: true,
|
||||
},
|
||||
).Build()
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
// Legacy config.
|
||||
b := r(`
|
||||
[build]
|
||||
writeStats = true
|
||||
`)
|
||||
|
||||
b.AssertFileContent("hugo_stats.json", "myclass", "div", "myid")
|
||||
|
||||
b = r(`
|
||||
[build]
|
||||
writeStats = false
|
||||
`)
|
||||
|
||||
b.AssertDestinationExists("hugo_stats.json", false)
|
||||
|
||||
b = r(`
|
||||
[build.buildStats]
|
||||
enable = true
|
||||
`)
|
||||
|
||||
b.AssertFileContent("hugo_stats.json", "myclass", "div", "myid")
|
||||
|
||||
b = r(`
|
||||
[build.buildStats]
|
||||
enable = true
|
||||
disableids = true
|
||||
`)
|
||||
|
||||
b.AssertFileContent("hugo_stats.json", "myclass", "div", "! myid")
|
||||
|
||||
b = r(`
|
||||
[build.buildStats]
|
||||
enable = true
|
||||
disableclasses = true
|
||||
`)
|
||||
|
||||
b.AssertFileContent("hugo_stats.json", "! myclass", "div", "myid")
|
||||
|
||||
b = r(`
|
||||
[build.buildStats]
|
||||
enable = true
|
||||
disabletags = true
|
||||
`)
|
||||
|
||||
b.AssertFileContent("hugo_stats.json", "myclass", "! div", "myid")
|
||||
|
||||
b = r(`
|
||||
[build.buildStats]
|
||||
enable = true
|
||||
disabletags = true
|
||||
disableclasses = true
|
||||
`)
|
||||
|
||||
b.AssertFileContent("hugo_stats.json", "! myclass", "! div", "myid")
|
||||
|
||||
b = r(`
|
||||
[build.buildStats]
|
||||
enable = false
|
||||
`)
|
||||
b.AssertDestinationExists("hugo_stats.json", false)
|
||||
|
||||
}
|
||||
|
||||
func TestClassCollectorStress(t *testing.T) {
|
||||
statsFilename := "hugo_stats.json"
|
||||
defer os.Remove(statsFilename)
|
||||
|
||||
+3
-2
@@ -1,7 +1,8 @@
|
||||
# Release env.
|
||||
# These will be replaced by script before release.
|
||||
HUGORELEASER_TAG=v0.115.0
|
||||
HUGORELEASER_COMMITISH=67caf50698783d3b3d78559ac81483d83e5e1a35
|
||||
HUGORELEASER_TAG=v0.115.1
|
||||
HUGORELEASER_COMMITISH=857374e69358f788bd31ddc55255c5c8e3dcfd80
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -119,7 +119,7 @@ func (t Translator) initFuncs(bndl *i18n.Bundle) {
|
||||
t.logger.Warnf("Failed to get translated string for language %q and ID %q: %s", currentLangStr, translationID, err)
|
||||
}
|
||||
|
||||
if t.cfg.LogI18nWarnings() {
|
||||
if t.cfg.PrintI18nWarnings() {
|
||||
t.logger.Warnf("i18n|MISSING_TRANSLATION|%s|%s", currentLangStr, translationID)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
|
||||
"golang.org/x/net/html"
|
||||
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/helpers"
|
||||
)
|
||||
|
||||
@@ -46,8 +47,9 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func newHTMLElementsCollector() *htmlElementsCollector {
|
||||
func newHTMLElementsCollector(conf config.BuildStats) *htmlElementsCollector {
|
||||
return &htmlElementsCollector{
|
||||
conf: conf,
|
||||
elementSet: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
@@ -93,6 +95,8 @@ type htmlElement struct {
|
||||
}
|
||||
|
||||
type htmlElementsCollector struct {
|
||||
conf config.BuildStats
|
||||
|
||||
// Contains the raw HTML string. We will get the same element
|
||||
// several times, and want to avoid costly reparsing when this
|
||||
// is used for aggregated data only.
|
||||
@@ -113,7 +117,9 @@ func (c *htmlElementsCollector) getHTMLElements() HTMLElements {
|
||||
for _, el := range c.elements {
|
||||
classes = append(classes, el.Classes...)
|
||||
ids = append(ids, el.IDs...)
|
||||
tags = append(tags, el.Tag)
|
||||
if !c.conf.DisableTags {
|
||||
tags = append(tags, el.Tag)
|
||||
}
|
||||
}
|
||||
|
||||
classes = helpers.UniqueStringsSorted(classes)
|
||||
@@ -246,7 +252,7 @@ func (w *htmlElementsCollectorWriter) lexElementInside(resolve htmlCollectorStat
|
||||
}
|
||||
|
||||
// Parse each collected element.
|
||||
el, err := parseHTMLElement(s)
|
||||
el, err := w.parseHTMLElement(s)
|
||||
if err != nil {
|
||||
w.err = err
|
||||
return resolve
|
||||
@@ -363,7 +369,8 @@ func htmlLexToEndOfComment(w *htmlElementsCollectorWriter) htmlCollectorStateFun
|
||||
return htmlLexToEndOfComment
|
||||
}
|
||||
|
||||
func parseHTMLElement(elStr string) (el htmlElement, err error) {
|
||||
func (w *htmlElementsCollectorWriter) parseHTMLElement(elStr string) (el htmlElement, err error) {
|
||||
conf := w.collector.conf
|
||||
|
||||
tagName := parseStartTag(elStr)
|
||||
|
||||
@@ -390,8 +397,13 @@ func parseHTMLElement(elStr string) (el htmlElement, err error) {
|
||||
switch {
|
||||
case strings.EqualFold(a.Key, "id"):
|
||||
// There should be only one, but one never knows...
|
||||
el.IDs = append(el.IDs, a.Val)
|
||||
if !conf.DisableIDs {
|
||||
el.IDs = append(el.IDs, a.Val)
|
||||
}
|
||||
default:
|
||||
if conf.DisableClasses {
|
||||
continue
|
||||
}
|
||||
if classAttrRe.MatchString(a.Key) {
|
||||
el.Classes = append(el.Classes, strings.Fields(a.Val)...)
|
||||
} else {
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/config/testconfig"
|
||||
"github.com/gohugoio/hugo/media"
|
||||
"github.com/gohugoio/hugo/minifiers"
|
||||
@@ -136,7 +137,9 @@ func TestClassCollector(t *testing.T) {
|
||||
} {
|
||||
|
||||
c.Run(fmt.Sprintf("%s--minify-%t", test.name, variant.minify), func(c *qt.C) {
|
||||
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
|
||||
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector(
|
||||
config.BuildStats{Enable: true},
|
||||
))
|
||||
if variant.minify {
|
||||
if skipMinifyTest[test.name] {
|
||||
c.Skip("skip minify test")
|
||||
@@ -240,7 +243,9 @@ func BenchmarkElementsCollectorWriter(b *testing.B) {
|
||||
</html>
|
||||
`
|
||||
for i := 0; i < b.N; i++ {
|
||||
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
|
||||
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector(
|
||||
config.BuildStats{Enable: true},
|
||||
))
|
||||
fmt.Fprint(w, benchHTML)
|
||||
|
||||
}
|
||||
@@ -262,7 +267,9 @@ func BenchmarkElementsCollectorWriterPre(b *testing.B) {
|
||||
<div class="foo"></div>
|
||||
|
||||
`
|
||||
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
|
||||
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector(
|
||||
config.BuildStats{Enable: true},
|
||||
))
|
||||
for i := 0; i < b.N; i++ {
|
||||
fmt.Fprint(w, benchHTML)
|
||||
|
||||
|
||||
@@ -81,8 +81,8 @@ func NewDestinationPublisher(rs *resources.Spec, outputFormats output.Formats, m
|
||||
fs := rs.BaseFs.PublishFs
|
||||
cfg := rs.Cfg
|
||||
var classCollector *htmlElementsCollector
|
||||
if rs.BuildConfig().WriteStats {
|
||||
classCollector = newHTMLElementsCollector()
|
||||
if rs.BuildConfig().BuildStats.Enabled() {
|
||||
classCollector = newHTMLElementsCollector(rs.BuildConfig().BuildStats)
|
||||
}
|
||||
pub = DestinationPublisher{fs: fs, htmlElementsCollector: classCollector}
|
||||
pub.min, err = minifiers.New(mediaTypes, outputFormats, cfg)
|
||||
|
||||
+11
-9
@@ -41,6 +41,17 @@ environment:
|
||||
pandoc_datadir: $SNAP/usr/share/pandoc
|
||||
PYTHONHOME: /usr:$SNAP/usr
|
||||
RUBYLIB: $SNAP/usr/lib/ruby/vendor_ruby/2.7.0:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/ruby/vendor_ruby/2.7.0:$SNAP/usr/lib/ruby/vendor_ruby:$SNAP/usr/lib/ruby/2.7.0:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/ruby/2.7.0
|
||||
# HUGO_SECURITY_EXEC_OSENV
|
||||
#
|
||||
# Default value:
|
||||
# (?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+)$
|
||||
# Bundled applications require additional access:
|
||||
# git: GIT_EXEC_PATH and LD_LIBRARY_PATH
|
||||
# npx: npm_config_{cache,init_module,userconfig}
|
||||
# pandoc: pandoc_datadir
|
||||
# rst2html: PYTHONHOME and SNAP
|
||||
# asciidoctor: RUBYLIB
|
||||
HUGO_SECURITY_EXEC_OSENV: (?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+|GIT_EXEC_PATH|LD_LIBRARY_PATH|npm_config_(cache|init_module|userconfig)|pandoc_datadir|PYTHONHOME|SNAP|RUBYLIB)$
|
||||
|
||||
apps:
|
||||
hugo:
|
||||
@@ -92,15 +103,6 @@ parts:
|
||||
export GOPATH=$(realpath ../go)
|
||||
export PATH=$GOPATH/bin:$PATH
|
||||
|
||||
echo " * Patch securityConfig.go to allow"
|
||||
echo " - GIT_EXEC_PATH and LD_LIBRARY_PATH to be passed to git"
|
||||
echo " - npm_config_{cache,init_module,userconfig} to be passed to npx"
|
||||
echo " - pandoc_datadir to be passed to pandoc"
|
||||
echo " - PYTHONHOME and SNAP to be passed to rst2html"
|
||||
echo " - RUBYLIB to be passed to asciidoctor"
|
||||
sed -i '/OsEnv: NewWhitelist/s/)\$/|GIT_EXEC_PATH|LD_LIBRARY_PATH|npm_config_(cache|init_module|userconfig)|pandoc_datadir|PYTHONHOME|RUBYLIB|SNAP&/' config/security/securityConfig.go
|
||||
git diff config/security/securityConfig.go
|
||||
|
||||
HUGO_BUILD_TAGS="extended"
|
||||
echo " * Building hugo (HUGO_BUILD_TAGS=\"$HUGO_BUILD_TAGS\")..."
|
||||
go build -v -ldflags "-X github.com/gohugoio/hugo/common/hugo.vendorInfo=snap:$(git describe --tags --always --match 'v[0-9]*' | sed 's/^v//; s/-/+git/; s/-g/./')" -tags "$HUGO_BUILD_TAGS"
|
||||
|
||||
Reference in New Issue
Block a user