mirror of
https://github.com/gohugoio/hugo.git
synced 2026-09-01 19:22:38 +00:00
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a3574f6f70 | |||
| 989454a52d | |||
| 1e91e46520 | |||
| 8a57d0f15f | |||
| b76c50ac18 | |||
| 1cdd17882c | |||
| e2fb0b0e80 | |||
| 88aea56683 | |||
| f4c11571bb | |||
| 54075acc29 | |||
| 8b52303e31 | |||
| 3d45d30a41 | |||
| 095157cd65 | |||
| 29cf87444f | |||
| 1b4dd436dd | |||
| 4414ef73f3 | |||
| a133393eda | |||
| 9197debbfe | |||
| c29897fac0 | |||
| c70ab27ceb | |||
| 510d98b778 | |||
| 7fd6762c16 | |||
| 584f052f39 | |||
| b76d71761e | |||
| c5dca3bdee | |||
| ec463c0977 | |||
| 4d2743e4c8 | |||
| c20f70d9a3 | |||
| 1b556216a8 | |||
| 106c8e6de6 | |||
| 03b33ecb5e | |||
| 9928122eb8 | |||
| 105d3bc32f | |||
| 3e46ba5ce2 | |||
| 4d1303512b | |||
| 9943c1bef0 | |||
| 766757310a | |||
| d71c07cf3c | |||
| b462980ac2 | |||
| 47678d8cbd | |||
| 18b9b6488b | |||
| ce44a8e835 | |||
| 64f40731f1 | |||
| 1140314be1 | |||
| 404fd9e512 | |||
| b1b0cdee3a | |||
| 3eea082903 |
@@ -4,7 +4,7 @@ parameters:
|
||||
defaults: &defaults
|
||||
resource_class: large
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser:1.22500.20100
|
||||
- image: bepsays/ci-hugoreleaser:1.22500.20300
|
||||
environment: &buildenv
|
||||
GOMODCACHE: /root/project/gomodcache
|
||||
version: 2
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
environment:
|
||||
<<: [*buildenv]
|
||||
docker:
|
||||
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22500.20100
|
||||
- image: bepsays/ci-hugoreleaser-linux-arm64:1.22500.20300
|
||||
steps:
|
||||
- *restore-cache
|
||||
- &attach-workspace
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Install Ruby
|
||||
uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0
|
||||
uses: ruby/setup-ruby@44511735964dcb71245e7e55f72539531f7bc0eb # v1.257.0
|
||||
with:
|
||||
ruby-version: "2.7"
|
||||
bundler-cache: true #
|
||||
|
||||
Vendored
+13
-2
@@ -25,6 +25,8 @@ import (
|
||||
|
||||
// DefaultConfig holds the default configuration for the HTTP cache.
|
||||
var DefaultConfig = Config{
|
||||
RespectCacheControlNoStoreInRequest: true,
|
||||
RespectCacheControlNoStoreInResponse: false,
|
||||
Cache: Cache{
|
||||
For: GlobMatcher{
|
||||
Excludes: []string{"**"},
|
||||
@@ -42,7 +44,13 @@ var DefaultConfig = Config{
|
||||
|
||||
// Config holds the configuration for the HTTP cache.
|
||||
type Config struct {
|
||||
// Configures the HTTP cache behavior (RFC 9111).
|
||||
// When enabled and there's a Cache-Control: no-store directive in the request, response will never be stored in disk cache.
|
||||
RespectCacheControlNoStoreInRequest bool
|
||||
|
||||
// When enabled and there's a Cache-Control: no-store directive in the response, response will never be stored in disk cache.
|
||||
RespectCacheControlNoStoreInResponse bool
|
||||
|
||||
// Enables HTTP cache behavior (RFC 9111) for these resources.
|
||||
// When this is not enabled for a resource, Hugo will go straight to the file cache.
|
||||
Cache Cache
|
||||
|
||||
@@ -57,7 +65,9 @@ type Cache struct {
|
||||
}
|
||||
|
||||
func (c *Config) Compile() (ConfigCompiled, error) {
|
||||
var cc ConfigCompiled
|
||||
cc := ConfigCompiled{
|
||||
Base: *c,
|
||||
}
|
||||
|
||||
p, err := c.Cache.For.CompilePredicate()
|
||||
if err != nil {
|
||||
@@ -127,6 +137,7 @@ func (gm GlobMatcher) IsZero() bool {
|
||||
}
|
||||
|
||||
type ConfigCompiled struct {
|
||||
Base Config
|
||||
For predicate.P[string]
|
||||
PollConfigs []PollConfigCompiled
|
||||
}
|
||||
|
||||
+1
-1
@@ -76,7 +76,7 @@ func flagsToCfgWithAdditionalConfigBase(cd *simplecobra.Commandeer, cfg config.P
|
||||
|
||||
// Flags with a different name in the config.
|
||||
keyMap := map[string]string{
|
||||
"minify": "minifyOutput",
|
||||
"minify": "minify.minifyOutput",
|
||||
"destination": "publishDir",
|
||||
"editor": "newContentEditor",
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/bep/debounce"
|
||||
"github.com/bep/simplecobra"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/gohugoio/hugo/common/herrors"
|
||||
@@ -515,6 +516,14 @@ func (c *hugoBuilder) doWithPublishDirs(f func(sourceFs *filesystems.SourceFiles
|
||||
return langCount, nil
|
||||
}
|
||||
|
||||
func (c *hugoBuilder) progressIntermediate() {
|
||||
terminal.ReportProgress(c.r.StdOut, terminal.ProgressIntermediate, 0)
|
||||
}
|
||||
|
||||
func (c *hugoBuilder) progressHidden() {
|
||||
terminal.ReportProgress(c.r.StdOut, terminal.ProgressHidden, 0)
|
||||
}
|
||||
|
||||
func (c *hugoBuilder) fullBuild(noBuildLock bool) error {
|
||||
var (
|
||||
g errgroup.Group
|
||||
@@ -1027,6 +1036,17 @@ func (c *hugoBuilder) hugoTry() *hugolib.HugoSites {
|
||||
}
|
||||
|
||||
func (c *hugoBuilder) loadConfig(cd *simplecobra.Commandeer, running bool) error {
|
||||
if terminal.PrintANSIColors(os.Stdout) {
|
||||
defer c.progressHidden()
|
||||
// If the configuration takes a while to load, we want to show some progress.
|
||||
// This is typically loading of external modules.
|
||||
d := debounce.New(500 * time.Millisecond)
|
||||
d(func() {
|
||||
c.progressIntermediate()
|
||||
})
|
||||
defer d(func() {})
|
||||
}
|
||||
|
||||
cfg := config.New()
|
||||
cfg.Set("renderToMemory", c.r.renderToMemory)
|
||||
watch := c.r.buildWatch || (c.s != nil && c.s.serverWatch)
|
||||
|
||||
@@ -86,6 +86,18 @@ func IsSlice(v any) bool {
|
||||
|
||||
var zeroType = reflect.TypeOf((*types.Zeroer)(nil)).Elem()
|
||||
|
||||
var isZeroCache sync.Map
|
||||
|
||||
func implementsIsZero(tp reflect.Type) bool {
|
||||
v, ok := isZeroCache.Load(tp)
|
||||
if ok {
|
||||
return v.(bool)
|
||||
}
|
||||
implements := tp.Implements(zeroType)
|
||||
isZeroCache.Store(tp, implements)
|
||||
return implements
|
||||
}
|
||||
|
||||
// IsTruthfulValue returns whether the given value has a meaningful truth value.
|
||||
// This is based on template.IsTrue in Go's stdlib, but also considers
|
||||
// IsZero and any interface value will be unwrapped before it's considered
|
||||
@@ -105,7 +117,7 @@ func IsTruthfulValue(val reflect.Value) (truth bool) {
|
||||
return
|
||||
}
|
||||
|
||||
if val.Type().Implements(zeroType) {
|
||||
if implementsIsZero(val.Type()) {
|
||||
return !val.Interface().(types.Zeroer).IsZero()
|
||||
}
|
||||
|
||||
|
||||
@@ -106,14 +106,26 @@ func BenchmarkIsContextType(b *testing.B) {
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkIsTruthFul(b *testing.B) {
|
||||
v := reflect.ValueOf("Hugo")
|
||||
func BenchmarkIsTruthFulValue(b *testing.B) {
|
||||
var (
|
||||
stringHugo = reflect.ValueOf("Hugo")
|
||||
stringEmpty = reflect.ValueOf("")
|
||||
zero = reflect.ValueOf(time.Time{})
|
||||
timeNow = reflect.ValueOf(time.Now())
|
||||
boolTrue = reflect.ValueOf(true)
|
||||
boolFalse = reflect.ValueOf(false)
|
||||
nilPointer = reflect.ValueOf((*zeroStruct)(nil))
|
||||
)
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
if !IsTruthfulValue(v) {
|
||||
b.Fatal("not truthful")
|
||||
}
|
||||
IsTruthfulValue(stringHugo)
|
||||
IsTruthfulValue(stringEmpty)
|
||||
IsTruthfulValue(zero)
|
||||
IsTruthfulValue(timeNow)
|
||||
IsTruthfulValue(boolTrue)
|
||||
IsTruthfulValue(boolFalse)
|
||||
IsTruthfulValue(nilPointer)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,6 @@ package hugo
|
||||
var CurrentVersion = Version{
|
||||
Major: 0,
|
||||
Minor: 151,
|
||||
PatchLevel: 0,
|
||||
Suffix: "-DEV",
|
||||
PatchLevel: 2,
|
||||
Suffix: "",
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ package terminal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@@ -72,3 +73,27 @@ func doublePercent(str string) string {
|
||||
func singlePercent(str string) string {
|
||||
return strings.Replace(str, "%%", "%", -1)
|
||||
}
|
||||
|
||||
type ProgressState int
|
||||
|
||||
const (
|
||||
ProgressHidden ProgressState = iota
|
||||
ProgressNormal
|
||||
ProgressError
|
||||
ProgressIntermediate
|
||||
ProgressWarning
|
||||
)
|
||||
|
||||
// ReportProgress writes OSC 9;4 sequence to w.
|
||||
func ReportProgress(w io.Writer, state ProgressState, progress float64) {
|
||||
if progress < 0 {
|
||||
progress = 0.0
|
||||
}
|
||||
if progress > 1 {
|
||||
progress = 1.0
|
||||
}
|
||||
|
||||
pi := int(progress * 100)
|
||||
|
||||
fmt.Fprintf(w, "\033]9;4;%d;%d\007", state, pi)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
{{ define "main" }}
|
||||
{{ .Content }}
|
||||
{{ range site.RegularPages }}
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ .Summary }}
|
||||
<section>
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ .Summary }}
|
||||
</section>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
<h1>{{ .Title }}</h1>
|
||||
{{ .Content }}
|
||||
{{ range .Pages }}
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ .Summary }}
|
||||
<section>
|
||||
<h2><a href="{{ .RelPermalink }}">{{ .LinkTitle }}</a></h2>
|
||||
{{ .Summary }}
|
||||
</section>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
+4
-1
@@ -1238,7 +1238,10 @@ config:
|
||||
enable: false
|
||||
superscript:
|
||||
enable: false
|
||||
footnote: true
|
||||
footnote:
|
||||
backlinkHTML: '↩︎'
|
||||
enable: true
|
||||
enableAutoIDPrefix: false
|
||||
linkify: true
|
||||
linkifyProtocol: https
|
||||
passthrough:
|
||||
|
||||
@@ -2,10 +2,11 @@ module github.com/gohugoio/hugo
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69
|
||||
github.com/JohannesKaufmann/html-to-markdown/v2 v2.4.0
|
||||
github.com/alecthomas/chroma/v2 v2.20.0
|
||||
github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c
|
||||
github.com/aws/aws-sdk-go-v2 v1.38.1
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.53.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.39.2
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.4
|
||||
github.com/bep/clocks v0.5.0
|
||||
github.com/bep/debounce v1.2.0
|
||||
github.com/bep/gitmap v1.9.0
|
||||
@@ -26,7 +27,7 @@ require (
|
||||
github.com/clbanning/mxj/v2 v2.7.0
|
||||
github.com/disintegration/gift v1.2.1
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/evanw/esbuild v0.25.9
|
||||
github.com/evanw/esbuild v0.25.11
|
||||
github.com/fatih/color v1.18.0
|
||||
github.com/fortytw2/leaktest v1.3.0
|
||||
github.com/frankban/quicktest v1.14.6
|
||||
@@ -36,8 +37,8 @@ require (
|
||||
github.com/gobuffalo/flect v1.0.3
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gohugoio/go-i18n/v2 v2.1.3-0.20230805085216-e63c13218d0e
|
||||
github.com/gohugoio/hashstructure v0.5.0
|
||||
github.com/gohugoio/httpcache v0.7.0
|
||||
github.com/gohugoio/hashstructure v0.6.0
|
||||
github.com/gohugoio/httpcache v0.8.0
|
||||
github.com/gohugoio/hugo-goldmark-extensions/extras v0.5.0
|
||||
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.3.1
|
||||
github.com/gohugoio/locales v0.14.0
|
||||
@@ -56,18 +57,18 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c
|
||||
github.com/muesli/smartcrop v0.3.0
|
||||
github.com/niklasfasching/go-org v1.9.1
|
||||
github.com/olekukonko/tablewriter v1.0.9
|
||||
github.com/olekukonko/tablewriter v1.1.0
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
|
||||
github.com/pelletier/go-toml/v2 v2.2.4
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
||||
github.com/rogpeppe/go-internal v1.14.1
|
||||
github.com/sanity-io/litter v1.5.8
|
||||
github.com/spf13/afero v1.14.0
|
||||
github.com/spf13/cast v1.9.2
|
||||
github.com/spf13/afero v1.15.0
|
||||
github.com/spf13/cast v1.10.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/fsync v0.10.1
|
||||
github.com/spf13/pflag v1.0.7
|
||||
github.com/tdewolff/minify/v2 v2.24.2
|
||||
github.com/tdewolff/minify/v2 v2.24.3
|
||||
github.com/tdewolff/parse/v2 v2.8.3
|
||||
github.com/tetratelabs/wazero v1.9.0
|
||||
github.com/yuin/goldmark v1.7.13
|
||||
@@ -75,13 +76,13 @@ require (
|
||||
go.uber.org/automaxprocs v1.5.3
|
||||
gocloud.dev v0.43.0
|
||||
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b
|
||||
golang.org/x/image v0.30.0
|
||||
golang.org/x/mod v0.28.0
|
||||
golang.org/x/net v0.43.0
|
||||
golang.org/x/sync v0.16.0
|
||||
golang.org/x/text v0.28.0
|
||||
golang.org/x/tools v0.36.0
|
||||
google.golang.org/api v0.248.0
|
||||
golang.org/x/image v0.32.0
|
||||
golang.org/x/mod v0.29.0
|
||||
golang.org/x/net v0.46.0
|
||||
golang.org/x/sync v0.17.0
|
||||
golang.org/x/text v0.30.0
|
||||
golang.org/x/tools v0.38.0
|
||||
google.golang.org/api v0.251.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
rsc.io/qr v0.2.0
|
||||
)
|
||||
@@ -91,7 +92,7 @@ require (
|
||||
cloud.google.com/go v0.121.4 // indirect
|
||||
cloud.google.com/go/auth v0.16.5 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.8.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.9.0 // indirect
|
||||
cloud.google.com/go/iam v1.5.2 // indirect
|
||||
cloud.google.com/go/monitoring v1.24.2 // indirect
|
||||
cloud.google.com/go/storage v1.55.0 // indirect
|
||||
@@ -105,14 +106,15 @@ require (
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0 // indirect
|
||||
github.com/JohannesKaufmann/dom v0.2.0 // indirect
|
||||
github.com/aws/aws-sdk-go v1.55.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.17 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.70 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.84 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect
|
||||
@@ -123,7 +125,7 @@ require (
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect
|
||||
github.com/aws/smithy-go v1.22.5 // indirect
|
||||
github.com/aws/smithy-go v1.23.0 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
@@ -162,7 +164,7 @@ require (
|
||||
github.com/perimeterx/marshmallow v1.1.5 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
|
||||
github.com/woodsbury/decimal128 v1.3.0 // indirect
|
||||
@@ -176,16 +178,16 @@ require (
|
||||
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.37.0 // indirect
|
||||
golang.org/x/crypto v0.41.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
golang.org/x/crypto v0.43.0 // indirect
|
||||
golang.org/x/oauth2 v0.31.0 // indirect
|
||||
golang.org/x/sys v0.37.0 // indirect
|
||||
golang.org/x/time v0.13.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
google.golang.org/genproto v0.0.0-20250715232539-7130f93afb79 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250715232539-7130f93afb79 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c // indirect
|
||||
google.golang.org/grpc v1.74.2 // indirect
|
||||
google.golang.org/protobuf v1.36.7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect
|
||||
google.golang.org/grpc v1.75.1 // indirect
|
||||
google.golang.org/protobuf v1.36.9 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
howett.net/plist v1.0.0 // indirect
|
||||
software.sslmate.com/src/go-pkcs12 v0.2.0 // indirect
|
||||
|
||||
@@ -31,8 +31,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA=
|
||||
cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw=
|
||||
cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs=
|
||||
cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8=
|
||||
@@ -91,6 +91,10 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.53.0/go.mod h1:jUZ5LYlw40WMd07qxcQJD5M40aUxrfwqQX1g7zxYnrQ=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0 h1:Ron4zCA/yk6U7WOBXhTJcDpsUBG9npumK6xw2auFltQ=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.53.0/go.mod h1:cSgYe11MCNYunTnRXrKiR/tHc0eoKjICUuWpNZoVCOo=
|
||||
github.com/JohannesKaufmann/dom v0.2.0 h1:1bragmEb19K8lHAqgFgqCpiPCFEZMTXzOIEjuxkUfLQ=
|
||||
github.com/JohannesKaufmann/dom v0.2.0/go.mod h1:57iSUl5RKric4bUkgos4zu6Xt5LMHUnw3TF1l5CbGZo=
|
||||
github.com/JohannesKaufmann/html-to-markdown/v2 v2.4.0 h1:C0/TerKdQX9Y9pbYi1EsLr5LDNANsqunyI/btpyfCg8=
|
||||
github.com/JohannesKaufmann/html-to-markdown/v2 v2.4.0/go.mod h1:OLaKh+giepO8j7teevrNwiy/fwf8LXgoc9g7rwaE1jk=
|
||||
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
|
||||
github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
|
||||
github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw=
|
||||
@@ -101,8 +105,8 @@ github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c h1:651/eoCRnQ7YtS
|
||||
github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/aws/aws-sdk-go v1.55.7 h1:UJrkFq7es5CShfBwlWAC8DA077vp8PyVbQd3lqLiztE=
|
||||
github.com/aws/aws-sdk-go v1.55.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/aws/aws-sdk-go-v2 v1.38.1 h1:j7sc33amE74Rz0M/PoCpsZQ6OunLqys/m5antM0J+Z8=
|
||||
github.com/aws/aws-sdk-go-v2 v1.38.1/go.mod h1:9Q0OoGQoboYIAJyslFyF1f5K1Ryddop8gqMhWx/n4Wg=
|
||||
github.com/aws/aws-sdk-go-v2 v1.39.2 h1:EJLg8IdbzgeD7xgvZ+I8M1e0fL0ptn/M47lianzth0I=
|
||||
github.com/aws/aws-sdk-go-v2 v1.39.2/go.mod h1:sDioUELIUO9Znk23YVmIk86/9DOpkbyyVb1i/gUNFXY=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11 h1:12SpdwU8Djs+YGklkinSSlcrPyj3H4VifVsKf78KbwA=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.11/go.mod h1:dd+Lkp6YmMryke+qxW/VnKyhMBDTYP41Q2Bb+6gNZgY=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.17 h1:jSuiQ5jEe4SAMH6lLRMY9OVC+TqJLP5655pBGjmnjr0=
|
||||
@@ -113,16 +117,16 @@ github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 h1:KAXP9JSHO1vKGCr5f4O6Wm
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32/go.mod h1:h4Sg6FQdexC1yYG9RDnOvLbW1a/P986++/Y/a+GyEM8=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.84 h1:cTXRdLkpBanlDwISl+5chq5ui1d1YWg4PWMR9c3kXyw=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.84/go.mod h1:kwSy5X7tfIHN39uucmjQVs2LvDdXEjQucgQQEqCggEo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4 h1:IdCLsiiIj5YJ3AFevsewURCPV+YWUlOW8JiPhoAy8vg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.4/go.mod h1:l4bdfCD7XyyZA9BolKBo1eLqgaJxl0/x91PL4Yqe0ao=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4 h1:j7vjtr1YIssWQOMeOWRbh3z8g2oY/xPjnZH2gLY4sGw=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.4/go.mod h1:yDmJgqOiH4EA8Hndnv4KwAo8jCGTSnM5ASG1nBI+toA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9 h1:se2vOWGD3dWQUtfn4wEjRQJb1HK1XsNIt825gskZ970=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.9/go.mod h1:hijCGH2VfbZQxqCDN7bwz/4dzxV+hkyhjawAtdPWKZA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9 h1:6RBnKZLkJM4hQ+kN6E7yWFveOTg8NLPHAkqrs4ZPlTU=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.9/go.mod h1:V9rQKRmK7AWuEsOMnHzKj8WyrIir1yUJbZxDuZLFvXI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36 h1:GMYy2EOWfzdP3wfVAGXBNKY5vK4K8vMET4sYOYltmqs=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.36/go.mod h1:gDhdAV6wL3PmPqBhiPbnlS447GoWs8HTTOYef9/9Inw=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.53.0 h1:fdPi8+XO2X3h+Z5fTArTVeThFOqf+8LBu+dxjXDx9dc=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.53.0/go.mod h1:zs9f9z7VhQZJ2TMUqYYst0uZTc7VTDzmoDcHf0VrmPs=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.4 h1:tVpbQcr1A0c+VTqtKEN9vfB0qer2SjfxX3LYojSGUq0=
|
||||
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.54.4/go.mod h1:dYwFVhUsRZt7COcGP23ei0lY8gX8ZSHrbyX49VB93MA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 h1:CXV68E2dNqhuynZJPB80bhPQwAKqBWVer887figW6Jc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4/go.mod h1:/xFi9KtvBXP97ppCz1TAEvU1Uf66qvid89rbem3wCzQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.4 h1:nAP2GYbfh8dd2zGZqFRSMlq+/F6cMPBUuCsGAMkN074=
|
||||
@@ -139,8 +143,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 h1:BpOxT3yhLwSJ77qIY3DoHAQj
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3/go.mod h1:vq/GQR1gOFLquZMSrxUK/cpvKCNVYibNyJ1m7JrU88E=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 h1:NFOJ/NXEGV4Rq//71Hs1jC/NvPs1ezajK+yQmkwnPV0=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.34.0/go.mod h1:7ph2tGpfQvwzgistp2+zga9f+bCjlQJPkPUmMgDSD7w=
|
||||
github.com/aws/smithy-go v1.22.5 h1:P9ATCXPMb2mPjYBgueqJNCA5S9UfktsW0tTxi+a7eqw=
|
||||
github.com/aws/smithy-go v1.22.5/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||
github.com/aws/smithy-go v1.23.0 h1:8n6I3gXzWJB2DxBDnfxgBaSX6oe0d/t10qGz7OKqMCE=
|
||||
github.com/aws/smithy-go v1.23.0/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/bep/clocks v0.5.0 h1:hhvKVGLPQWRVsBP/UB7ErrHYIO42gINVbvqxvYTPVps=
|
||||
@@ -221,8 +225,8 @@ github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJP
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
|
||||
github.com/evanw/esbuild v0.25.9 h1:aU7GVC4lxJGC1AyaPwySWjSIaNLAdVEEuq3chD0Khxs=
|
||||
github.com/evanw/esbuild v0.25.9/go.mod h1:D2vIQZqV/vIf/VRHtViaUtViZmG7o+kKmlBfVQuRi48=
|
||||
github.com/evanw/esbuild v0.25.11 h1:NGtezc+xk+Mti4fgWaoD3dncZNCzcTA+r0BxMV3Koyw=
|
||||
github.com/evanw/esbuild v0.25.11/go.mod h1:D2vIQZqV/vIf/VRHtViaUtViZmG7o+kKmlBfVQuRi48=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
@@ -264,10 +268,10 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gohugoio/go-i18n/v2 v2.1.3-0.20230805085216-e63c13218d0e h1:QArsSubW7eDh8APMXkByjQWvuljwPGAGQpJEFn0F0wY=
|
||||
github.com/gohugoio/go-i18n/v2 v2.1.3-0.20230805085216-e63c13218d0e/go.mod h1:3Ltoo9Banwq0gOtcOwxuHG6omk+AwsQPADyw2vQYOJQ=
|
||||
github.com/gohugoio/hashstructure v0.5.0 h1:G2fjSBU36RdwEJBWJ+919ERvOVqAg9tfcYp47K9swqg=
|
||||
github.com/gohugoio/hashstructure v0.5.0/go.mod h1:Ser0TniXuu/eauYmrwM4o64EBvySxNzITEOLlm4igec=
|
||||
github.com/gohugoio/httpcache v0.7.0 h1:ukPnn04Rgvx48JIinZvZetBfHaWE7I01JR2Q2RrQ3Vs=
|
||||
github.com/gohugoio/httpcache v0.7.0/go.mod h1:fMlPrdY/vVJhAriLZnrF5QpN3BNAcoBClgAyQd+lGFI=
|
||||
github.com/gohugoio/hashstructure v0.6.0 h1:7wMB/2CfXoThFYhdWRGv3u3rUM761Cq29CxUW+NltUg=
|
||||
github.com/gohugoio/hashstructure v0.6.0/go.mod h1:lapVLk9XidheHG1IQ4ZSbyYrXcaILU1ZEP/+vno5rBQ=
|
||||
github.com/gohugoio/httpcache v0.8.0 h1:hNdsmGSELztetYCsPVgjA960zSa4dfEqqF/SficorCU=
|
||||
github.com/gohugoio/httpcache v0.8.0/go.mod h1:fMlPrdY/vVJhAriLZnrF5QpN3BNAcoBClgAyQd+lGFI=
|
||||
github.com/gohugoio/hugo-goldmark-extensions/extras v0.5.0 h1:dco+7YiOryRoPOMXwwaf+kktZSCtlFtreNdiJbETvYE=
|
||||
github.com/gohugoio/hugo-goldmark-extensions/extras v0.5.0/go.mod h1:CRrxQTKeM3imw+UoS4EHKyrqB7Zp6sAJiqHit+aMGTE=
|
||||
github.com/gohugoio/hugo-goldmark-extensions/passthrough v0.3.1 h1:nUzXfRTszLliZuN0JTKeunXTRaiFX6ksaWP0puLLYAY=
|
||||
@@ -438,8 +442,8 @@ github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5
|
||||
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
|
||||
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
|
||||
github.com/olekukonko/tablewriter v1.0.9 h1:XGwRsYLC2bY7bNd93Dk51bcPZksWZmLYuaTHR0FqfL8=
|
||||
github.com/olekukonko/tablewriter v1.0.9/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
|
||||
github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY=
|
||||
github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
@@ -463,8 +467,9 @@ github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI=
|
||||
github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
@@ -475,12 +480,16 @@ github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd h1:CmH9+J6ZSsIjUK
|
||||
github.com/rwcarlsen/goexif v0.0.0-20190401172101-9e8deecbddbd/go.mod h1:hPqNNc0+uJM6H+SuU8sEs5K5IQeKccPqeSjfgcKGgPk=
|
||||
github.com/sanity-io/litter v1.5.8 h1:uM/2lKrWdGbRXDrIq08Lh9XtVYoeGtcQxk9rtQ7+rYg=
|
||||
github.com/sanity-io/litter v1.5.8/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
||||
github.com/sebdah/goldie/v2 v2.7.1 h1:PkBHymaYdtvEkZV7TmyqKxdmn5/Vcj+8TpATWZjnG5E=
|
||||
github.com/sebdah/goldie/v2 v2.7.1/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw=
|
||||
github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/shogo82148/go-shuffle v0.0.0-20180218125048-27e6095f230d/go.mod h1:2htx6lmL0NGLHlO8ZCf+lQBGBHIbEujyywxJArf+2Yc=
|
||||
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
|
||||
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
|
||||
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
|
||||
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/fsync v0.10.1 h1:JRnB7G72b+gIBaBcpn5ibJSd7ww1iEahXSX2B8G6dSE=
|
||||
@@ -503,8 +512,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tdewolff/minify/v2 v2.24.2 h1:vnY3nTulEAbCAAlxTxPPDkzG24rsq31SOzp63yT+7mo=
|
||||
github.com/tdewolff/minify/v2 v2.24.2/go.mod h1:1JrCtoZXaDbqioQZfk3Jdmr0GPJKiU7c1Apmb+7tCeE=
|
||||
github.com/tdewolff/minify/v2 v2.24.3 h1:BaKgWSFLKbKDiUskbeRgbe2n5d1Ci1x3cN/eXna8zOA=
|
||||
github.com/tdewolff/minify/v2 v2.24.3/go.mod h1:1JrCtoZXaDbqioQZfk3Jdmr0GPJKiU7c1Apmb+7tCeE=
|
||||
github.com/tdewolff/parse/v2 v2.8.3 h1:5VbvtJ83cfb289A1HzRA9sf02iT8YyUwN84ezjkdY1I=
|
||||
github.com/tdewolff/parse/v2 v2.8.3/go.mod h1:Hwlni2tiVNKyzR1o6nUs4FOF07URA+JLBLd6dlIXYqo=
|
||||
github.com/tdewolff/test v1.0.11 h1:FdLbwQVHxqG16SlkGveC0JVyrJN62COWTRyUFzfbtBE=
|
||||
@@ -570,8 +579,8 @@ golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5y
|
||||
golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -587,8 +596,8 @@ golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4QTo5u+SEIbbKW1Rac
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4=
|
||||
golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c=
|
||||
golang.org/x/image v0.32.0 h1:6lZQWq75h7L5IWNk0r+SCpUJ6tUVd3v4ZHnbRKLkUDQ=
|
||||
golang.org/x/image v0.32.0/go.mod h1:/R37rrQmKXtO6tYXAjtDLwQgFLHmhW+V6ayXlxzP2Pc=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -615,8 +624,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -655,8 +664,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -666,8 +675,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo=
|
||||
golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -683,8 +692,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -732,8 +741,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
|
||||
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -752,13 +761,13 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
|
||||
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
@@ -811,14 +820,16 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
golang.org/x/tools v0.38.0 h1:Hx2Xv8hISq8Lm16jvBZ2VQf+RLmbd7wVUsALibYI/IQ=
|
||||
golang.org/x/tools v0.38.0/go.mod h1:yEsQ/d/YK8cjh0L6rZlY8tgtlKiBNTL14pGDJPJpYQs=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
|
||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
|
||||
@@ -838,8 +849,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
|
||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||
google.golang.org/api v0.248.0 h1:hUotakSkcwGdYUqzCRc5yGYsg4wXxpkKlW5ryVqvC1Y=
|
||||
google.golang.org/api v0.248.0/go.mod h1:yAFUAF56Li7IuIQbTFoLwXTCI6XCFKueOlS7S9e4F9k=
|
||||
google.golang.org/api v0.251.0 h1:6lea5nHRT8RUmpy9kkC2PJYnhnDAB13LqrLSVQlMIE8=
|
||||
google.golang.org/api v0.251.0/go.mod h1:Rwy0lPf/TD7+T2VhYcffCHhyyInyuxGjICxdfLqT7KI=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
@@ -887,8 +898,8 @@ google.golang.org/genproto v0.0.0-20250715232539-7130f93afb79 h1:Nt6z9UHqSlIdIGJ
|
||||
google.golang.org/genproto v0.0.0-20250715232539-7130f93afb79/go.mod h1:kTmlBHMPqR5uCZPBvwa2B18mvubkjyY3CRLI0c6fj0s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250715232539-7130f93afb79 h1:iOye66xuaAK0WnkPuhQPUFy8eJcmwUXqGGP3om6IxX8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250715232539-7130f93afb79/go.mod h1:HKJDgKsFUnv5VAGeQjz8kxcgDP0HoE0iZNp0OdZNlhE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c h1:qXWI/sQtv5UKboZ/zUk7h+mrf/lXORyI+n9DKDAusdg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250818200422-3122310a409c/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
@@ -905,8 +916,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
|
||||
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.74.2 h1:WoosgB65DlWVC9FqI82dGsZhWFNBSLjQ84bjROOpMu4=
|
||||
google.golang.org/grpc v1.74.2/go.mod h1:CtQ+BGjaAIXHs/5YS3i473GqwBBa1zGQNevxdeBEXrM=
|
||||
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
|
||||
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@@ -917,8 +928,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.36.7 h1:IgrO7UwFQGJdRNXH/sQux4R1Dj1WAKcLElzeeRaXV2A=
|
||||
google.golang.org/protobuf v1.36.7/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
|
||||
@@ -1760,6 +1760,13 @@ func (sa *sitePagesAssembler) assembleResources() error {
|
||||
duplicateResourceFiles = ps.s.ContentSpec.Converters.GetMarkupConfig().Goldmark.DuplicateResourceFiles
|
||||
}
|
||||
|
||||
if !sa.h.isRebuild() {
|
||||
if ps.hasRenderableOutput() {
|
||||
// For multi output pages this will not be complete, but will have to do for now.
|
||||
sa.h.progressReporter.numPagesToRender.Add(1)
|
||||
}
|
||||
}
|
||||
|
||||
duplicateResourceFiles = duplicateResourceFiles || ps.s.Conf.IsMultihost()
|
||||
|
||||
err := sa.pageMap.forEachResourceInPage(
|
||||
|
||||
@@ -279,9 +279,9 @@ P1: {{ $p1.Title }}|{{ $p1.Params.foo }}|{{ $p1.File.Filename }}|
|
||||
`
|
||||
|
||||
for range 3 {
|
||||
b := Test(t, files, TestOptWarn())
|
||||
b := Test(t, files, TestOptInfo())
|
||||
|
||||
b.AssertLogContains("WARN Duplicate content path: \"/p1\"")
|
||||
b.AssertLogContains("INFO Duplicate content path: \"/p1\"")
|
||||
|
||||
// There's multiple content files sharing the same logical path and language.
|
||||
// This is a little arbitrary, but we have to pick one and prefer the Markdown version.
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/cache/dynacache"
|
||||
@@ -33,9 +34,11 @@ import (
|
||||
"github.com/gohugoio/hugo/output"
|
||||
"github.com/gohugoio/hugo/parser/metadecoders"
|
||||
|
||||
"github.com/gohugoio/hugo/common/htime"
|
||||
"github.com/gohugoio/hugo/common/hugo"
|
||||
"github.com/gohugoio/hugo/common/maps"
|
||||
"github.com/gohugoio/hugo/common/para"
|
||||
"github.com/gohugoio/hugo/common/terminal"
|
||||
"github.com/gohugoio/hugo/common/types"
|
||||
"github.com/gohugoio/hugo/hugofs"
|
||||
|
||||
@@ -98,12 +101,29 @@ type HugoSites struct {
|
||||
numWorkersSites int
|
||||
numWorkers int
|
||||
|
||||
*progressReporter
|
||||
*fatalErrorHandler
|
||||
*buildCounters
|
||||
// Tracks invocations of the Build method.
|
||||
buildCounter atomic.Uint64
|
||||
}
|
||||
|
||||
type progressReporter struct {
|
||||
mu sync.Mutex
|
||||
t time.Time
|
||||
progress float64
|
||||
queue []func() (state terminal.ProgressState, progress float64)
|
||||
state terminal.ProgressState
|
||||
renderProgressStart float64
|
||||
numPagesToRender atomic.Uint64
|
||||
}
|
||||
|
||||
func (p *progressReporter) Start() {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
p.t = htime.Now()
|
||||
}
|
||||
|
||||
// ShouldSkipFileChangeEvent allows skipping filesystem event early before
|
||||
// the build is started.
|
||||
func (h *HugoSites) ShouldSkipFileChangeEvent(ev fsnotify.Event) bool {
|
||||
@@ -254,6 +274,64 @@ func (h *HugoSites) codeownersForPage(p page.Page) ([]string, error) {
|
||||
return h.codeownerInfo.forPage(p), nil
|
||||
}
|
||||
|
||||
func (h *HugoSites) reportProgress(f func() (state terminal.ProgressState, progress float64)) {
|
||||
h.progressReporter.mu.Lock()
|
||||
defer h.progressReporter.mu.Unlock()
|
||||
|
||||
if h.progressReporter.t.IsZero() {
|
||||
// Not started yet, queue it up and return.
|
||||
h.progressReporter.queue = append(h.progressReporter.queue, f)
|
||||
return
|
||||
}
|
||||
|
||||
handleOne := func(skip func(state terminal.ProgressState, progress float64) bool, handle func() (state terminal.ProgressState, progress float64)) {
|
||||
state, progress := handle()
|
||||
if skip != nil && skip(state, progress) {
|
||||
return
|
||||
}
|
||||
|
||||
if h.progressReporter.progress > 0 && h.progressReporter.state == state && progress <= h.progressReporter.progress {
|
||||
// Only report progress forward.
|
||||
return
|
||||
}
|
||||
|
||||
h.progressReporter.state = state
|
||||
h.progressReporter.progress = progress
|
||||
terminal.ReportProgress(h.Log.StdOut(), state, h.progressReporter.progress)
|
||||
}
|
||||
|
||||
// Drain queue first.
|
||||
skip := func(state terminal.ProgressState, progress float64) bool {
|
||||
// Skip qued up intermediate states if we already are in normal state.
|
||||
return h.progressReporter.state == terminal.ProgressNormal && state == terminal.ProgressIntermediate
|
||||
}
|
||||
for _, ff := range h.progressReporter.queue {
|
||||
handleOne(skip, ff)
|
||||
}
|
||||
h.progressReporter.queue = nil
|
||||
|
||||
handleOne(nil, f)
|
||||
}
|
||||
|
||||
func (h *HugoSites) onPageRender() {
|
||||
pagesRendered := h.buildCounters.pageRenderCounter.Add(1)
|
||||
numPagesToRender := h.progressReporter.numPagesToRender.Load()
|
||||
n := numPagesToRender / 30
|
||||
if n == 0 {
|
||||
n = 1
|
||||
}
|
||||
if pagesRendered%n == 0 {
|
||||
h.reportProgress(func() (terminal.ProgressState, float64) {
|
||||
pr := h.progressReporter
|
||||
if pr.renderProgressStart == 0.0 && pr.state == terminal.ProgressNormal {
|
||||
pr.renderProgressStart = pr.progress
|
||||
}
|
||||
pagesProgress := pr.renderProgressStart + float64(pagesRendered)/float64(numPagesToRender)*(1.0-pr.renderProgressStart)
|
||||
return terminal.ProgressNormal, pagesProgress
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (h *HugoSites) pickOneAndLogTheRest(errors []error) error {
|
||||
if len(errors) == 0 {
|
||||
return nil
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/bep/debounce"
|
||||
"github.com/bep/logg"
|
||||
"github.com/gohugoio/hugo/bufferpool"
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
@@ -45,6 +46,7 @@ import (
|
||||
"github.com/gohugoio/hugo/common/para"
|
||||
"github.com/gohugoio/hugo/common/paths"
|
||||
"github.com/gohugoio/hugo/common/rungroup"
|
||||
"github.com/gohugoio/hugo/common/terminal"
|
||||
"github.com/gohugoio/hugo/config"
|
||||
"github.com/gohugoio/hugo/resources/page"
|
||||
"github.com/gohugoio/hugo/resources/page/siteidentities"
|
||||
@@ -58,9 +60,25 @@ import (
|
||||
// Build builds all sites. If filesystem events are provided,
|
||||
// this is considered to be a potential partial rebuild.
|
||||
func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
|
||||
if !h.isRebuild() && terminal.PrintANSIColors(os.Stdout) {
|
||||
// Don't show progress for fast builds.
|
||||
d := debounce.New(250 * time.Millisecond)
|
||||
d(func() {
|
||||
h.progressReporter.Start()
|
||||
h.reportProgress(func() (state terminal.ProgressState, progress float64) {
|
||||
// We don't know how many files to process below, so use the intermediate state as the first progress.
|
||||
return terminal.ProgressIntermediate, 1.0
|
||||
})
|
||||
})
|
||||
defer d(func() {})
|
||||
}
|
||||
|
||||
infol := h.Log.InfoCommand("build")
|
||||
defer loggers.TimeTrackf(infol, time.Now(), nil, "")
|
||||
defer func() {
|
||||
h.reportProgress(func() (state terminal.ProgressState, progress float64) {
|
||||
return terminal.ProgressHidden, 1.0
|
||||
})
|
||||
h.buildCounter.Add(1)
|
||||
}()
|
||||
|
||||
@@ -148,10 +166,15 @@ func (h *HugoSites) Build(config BuildCfg, events ...fsnotify.Event) error {
|
||||
if err := h.process(ctx, infol, conf, init, events...); err != nil {
|
||||
return fmt.Errorf("process: %w", err)
|
||||
}
|
||||
|
||||
h.reportProgress(func() (state terminal.ProgressState, progress float64) {
|
||||
return terminal.ProgressNormal, 0.15
|
||||
})
|
||||
if err := h.assemble(ctx, infol, conf); err != nil {
|
||||
return fmt.Errorf("assemble: %w", err)
|
||||
}
|
||||
h.reportProgress(func() (state terminal.ProgressState, progress float64) {
|
||||
return terminal.ProgressNormal, 0.20
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -56,3 +56,187 @@ Len Resources: {{ len .Resources }}|
|
||||
b.AssertFileContent("public/en/index.html", "Home", "0|/en/myfiles/file1.txt|file 1 en|\n\n1|/en/myfiles/file2.txt|file 2 en|")
|
||||
b.AssertFileContent("public/nn/index.html", "Heim", "0|/nn/myfiles/file1.txt|file 1 nn|\n\n1|/en/myfiles/file2.txt|file 2 en|")
|
||||
}
|
||||
|
||||
func TestContentMountMerge(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- config.toml --
|
||||
baseURL = 'https://example.org/'
|
||||
languageCode = 'en-us'
|
||||
title = 'Hugo Forum Topic #37225'
|
||||
theme = 'mytheme'
|
||||
|
||||
disableKinds = ['sitemap','RSS','taxonomy','term']
|
||||
defaultContentLanguage = 'en'
|
||||
defaultContentLanguageInSubdir = true
|
||||
|
||||
[languages.en]
|
||||
languageName = 'English'
|
||||
weight = 1
|
||||
[languages.de]
|
||||
languageName = 'Deutsch'
|
||||
weight = 2
|
||||
[languages.nl]
|
||||
languageName = 'Nederlands'
|
||||
weight = 3
|
||||
|
||||
# EN content
|
||||
[[module.mounts]]
|
||||
source = 'content/en'
|
||||
target = 'content'
|
||||
lang = 'en'
|
||||
|
||||
# DE content
|
||||
[[module.mounts]]
|
||||
source = 'content/de'
|
||||
target = 'content'
|
||||
lang = 'de'
|
||||
|
||||
# This fills in the gaps in DE content with EN content
|
||||
[[module.mounts]]
|
||||
source = 'content/en'
|
||||
target = 'content'
|
||||
lang = 'de'
|
||||
|
||||
# NL content
|
||||
[[module.mounts]]
|
||||
source = 'content/nl'
|
||||
target = 'content'
|
||||
lang = 'nl'
|
||||
|
||||
# This should fill in the gaps in NL content with EN content
|
||||
[[module.mounts]]
|
||||
source = 'content/en'
|
||||
target = 'content'
|
||||
lang = 'nl'
|
||||
|
||||
-- content/de/_index.md --
|
||||
---
|
||||
title: "home (de)"
|
||||
---
|
||||
-- content/de/p1.md --
|
||||
---
|
||||
title: "p1 (de)"
|
||||
---
|
||||
-- content/en/_index.md --
|
||||
---
|
||||
title: "home (en)"
|
||||
---
|
||||
-- content/en/p1.md --
|
||||
---
|
||||
title: "p1 (en)"
|
||||
---
|
||||
-- content/en/p2.md --
|
||||
---
|
||||
title: "p2 (en)"
|
||||
---
|
||||
-- content/en/p3.md --
|
||||
---
|
||||
title: "p3 (en)"
|
||||
---
|
||||
-- content/nl/_index.md --
|
||||
---
|
||||
title: "home (nl)"
|
||||
---
|
||||
-- content/nl/p1.md --
|
||||
---
|
||||
title: "p1 (nl)"
|
||||
---
|
||||
-- content/nl/p3.md --
|
||||
---
|
||||
title: "p3 (nl)"
|
||||
---
|
||||
-- layouts/home.html --
|
||||
{{ .Title }}: {{ site.Language.Lang }}: {{ range site.RegularPages }}{{ .Title }}|{{ end }}:END
|
||||
-- themes/mytheme/config.toml --
|
||||
[[module.mounts]]
|
||||
source = 'content/nlt'
|
||||
target = 'content'
|
||||
lang = 'nl'
|
||||
-- themes/mytheme/content/nlt/p3.md --
|
||||
---
|
||||
title: "p3 theme (nl)"
|
||||
---
|
||||
-- themes/mytheme/content/nlt/p4.md --
|
||||
---
|
||||
title: "p4 theme (nl)"
|
||||
---
|
||||
`
|
||||
|
||||
b := NewIntegrationTestBuilder(
|
||||
IntegrationTestConfig{
|
||||
T: t,
|
||||
TxtarString: files,
|
||||
},
|
||||
).Build()
|
||||
|
||||
b.AssertFileContent("public/nl/index.html", `home (nl): nl: p1 (nl)|p2 (en)|p3 (nl)|p4 theme (nl)|:END`)
|
||||
b.AssertFileContent("public/de/index.html", `home (de): de: p1 (de)|p2 (en)|p3 (en)|:END`)
|
||||
b.AssertFileContent("public/en/index.html", `home (en): en: p1 (en)|p2 (en)|p3 (en)|:END`)
|
||||
}
|
||||
|
||||
// Issue 13993
|
||||
func TestIssue13993(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
disableKinds = ['home','rss','section','sitemap','taxonomy','term']
|
||||
printPathWarnings = true
|
||||
|
||||
defaultContentLanguage = 'en'
|
||||
defaultContentLanguageInSubdir = true
|
||||
|
||||
[languages.en]
|
||||
contentDir = "content/en"
|
||||
weight = 1
|
||||
|
||||
[languages.es]
|
||||
contentDir = "content/es"
|
||||
weight = 2
|
||||
|
||||
# Default content mounts
|
||||
|
||||
[[module.mounts]]
|
||||
source = "content/en"
|
||||
target = "content"
|
||||
lang = "en"
|
||||
|
||||
[[module.mounts]]
|
||||
source = "content/es"
|
||||
target = "content"
|
||||
lang = "es"
|
||||
|
||||
# Populate the missing es content with en content
|
||||
|
||||
[[module.mounts]]
|
||||
source = "content/en"
|
||||
target = "content"
|
||||
lang = "es"
|
||||
-- layouts/all.html --
|
||||
{{ .Title }}
|
||||
-- content/en/p1.md --
|
||||
---
|
||||
title: p1 (en)
|
||||
---
|
||||
-- content/en/p2.md --
|
||||
---
|
||||
title: p2 (en)
|
||||
---
|
||||
-- content/es/p1.md --
|
||||
---
|
||||
title: p1 (es)
|
||||
---
|
||||
`
|
||||
|
||||
b := Test(t, files, TestOptInfo())
|
||||
|
||||
b.AssertFileExists("public/en/p1/index.html", true)
|
||||
b.AssertFileExists("public/en/p2/index.html", true)
|
||||
b.AssertFileExists("public/es/p1/index.html", true)
|
||||
b.AssertFileExists("public/es/p2/index.html", true)
|
||||
|
||||
b.AssertLogContains("INFO Duplicate")
|
||||
b.AssertLogContains("! WARN Duplicate")
|
||||
}
|
||||
|
||||
@@ -113,6 +113,17 @@ type pageState struct {
|
||||
dependencyManager identity.Manager
|
||||
}
|
||||
|
||||
// This is not accurate and only used for progress reporting.
|
||||
// We can do better, but this will do for now.
|
||||
func (p *pageState) hasRenderableOutput() bool {
|
||||
for _, po := range p.pageOutputs {
|
||||
if po.render {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (p *pageState) incrPageOutputTemplateVariation() {
|
||||
p.pageOutputTemplateVariationsState.Add(1)
|
||||
}
|
||||
|
||||
@@ -794,11 +794,9 @@ func (p *pageMeta) newContentConverter(ps *pageState, markup string) (converter.
|
||||
return converter.NopConverter, fmt.Errorf("no content renderer found for markup %q, page: %s", markup, ps.getPageInfoForError())
|
||||
}
|
||||
|
||||
var id string
|
||||
var filename string
|
||||
var path string
|
||||
if p.f != nil {
|
||||
id = p.f.UniqueID()
|
||||
filename = p.f.Filename()
|
||||
path = p.f.Path()
|
||||
} else {
|
||||
@@ -822,7 +820,7 @@ func (p *pageMeta) newContentConverter(ps *pageState, markup string) (converter.
|
||||
converter.DocumentContext{
|
||||
Document: doc,
|
||||
DocumentLookup: documentLookup,
|
||||
DocumentID: id,
|
||||
DocumentID: hashing.XxHashFromStringHexEncoded(p.Path()),
|
||||
DocumentName: path,
|
||||
Filename: filename,
|
||||
},
|
||||
|
||||
@@ -118,7 +118,7 @@ func (c *pagesCollector) Collect() (collectErr error) {
|
||||
logFilesProcessed(true)
|
||||
}()
|
||||
|
||||
c.g = rungroup.Run[hugofs.FileMetaInfo](c.ctx, rungroup.Config[hugofs.FileMetaInfo]{
|
||||
c.g = rungroup.Run(c.ctx, rungroup.Config[hugofs.FileMetaInfo]{
|
||||
NumWorkers: numWorkers,
|
||||
Handle: func(ctx context.Context, fi hugofs.FileMetaInfo) error {
|
||||
numPages, numResources, err := c.m.AddFi(fi, c.buildConfig)
|
||||
@@ -334,7 +334,7 @@ func (c *pagesCollector) collectDirDir(path string, root hugofs.FileMetaInfo, in
|
||||
baseLang := hstrings.Strings2{pi.Base(), meta.Lang}
|
||||
if fi2, ok := seen[baseLang]; ok {
|
||||
if c.h.Configs.Base.PrintPathWarnings && !c.h.isRebuild() {
|
||||
c.logger.Warnf("Duplicate content path: %q file: %q file: %q", pi.Base(), fi2.Meta().Filename, meta.Filename)
|
||||
c.logger.Infof("Duplicate content path: %q file: %q file: %q", pi.Base(), fi2.Meta().Filename, meta.Filename)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
+2
-1
@@ -360,6 +360,7 @@ func newHugoSites(cfg deps.DepsCfg, d *deps.Deps, pageTrees *pageTrees, sites []
|
||||
data: lazy.New(),
|
||||
gitInfo: lazy.New(),
|
||||
},
|
||||
progressReporter: &progressReporter{},
|
||||
}
|
||||
|
||||
// Assemble dependencies to be used in hugo.Deps.
|
||||
@@ -1440,7 +1441,7 @@ const (
|
||||
)
|
||||
|
||||
func (s *Site) renderAndWritePage(statCounter *uint64, name string, targetPath string, p *pageState, d any, templ *tplimpl.TemplInfo) error {
|
||||
s.h.buildCounters.pageRenderCounter.Add(1)
|
||||
s.h.onPageRender()
|
||||
renderBuffer := bp.GetBuffer()
|
||||
defer bp.PutBuffer(renderBuffer)
|
||||
|
||||
|
||||
+5
-2
@@ -1,7 +1,10 @@
|
||||
# Release env.
|
||||
# These will be replaced by script before release.
|
||||
HUGORELEASER_TAG=v0.150.0
|
||||
HUGORELEASER_COMMITISH=3f5473b7d4e7377e807290c3acc89feeef1aaa71
|
||||
HUGORELEASER_TAG=v0.151.1
|
||||
HUGORELEASER_COMMITISH=1cdd17882c28a9f23278d38ef03b403954cfb1e5
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ func (r *htmlRenderer) renderBlockquote(w util.BufWriter, src []byte, node ast.N
|
||||
return ast.WalkContinue, nil
|
||||
}
|
||||
|
||||
text := strings.TrimSpace(ctx.PopRenderedString())
|
||||
text := ctx.PopRenderedString()
|
||||
|
||||
ordinal := ctx.GetAndIncrementOrdinal(ast.KindBlockquote)
|
||||
|
||||
@@ -90,7 +90,7 @@ func (r *htmlRenderer) renderBlockquote(w util.BufWriter, src []byte, node ast.N
|
||||
// tag if the first line of the blockquote content does not have a
|
||||
// closing p tag. At some point we might want to move this to the
|
||||
// parser.
|
||||
before, after, found := strings.Cut(text, "\n")
|
||||
before, after, found := strings.Cut(strings.TrimSpace(text), "\n")
|
||||
if found {
|
||||
if strings.HasSuffix(before, "</p>") {
|
||||
text = after
|
||||
@@ -173,7 +173,7 @@ func (c *blockquoteContext) Text() hstring.HTML {
|
||||
var blockQuoteAlertRe = regexp.MustCompile(`^<p>\[!([a-zA-Z]+)\](-|\+)?[^\S\r\n]?([^\n]*)\n?`)
|
||||
|
||||
func resolveBlockQuoteAlert(s string) blockQuoteAlert {
|
||||
m := blockQuoteAlertRe.FindStringSubmatch(s)
|
||||
m := blockQuoteAlertRe.FindStringSubmatch(strings.TrimSpace(s))
|
||||
if len(m) == 4 {
|
||||
title := strings.TrimSpace(m[3])
|
||||
title = strings.TrimSuffix(title, "</p>")
|
||||
|
||||
@@ -15,6 +15,7 @@ package blockquotes_test
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gohugoio/hugo/hugolib"
|
||||
@@ -76,7 +77,7 @@ title: "p1"
|
||||
"Blockquote Alert: |<p>This is a note with some whitespace after the alert type.</p>|alert|",
|
||||
"Blockquote Alert: |<p>This is a tip.</p>",
|
||||
"Blockquote Alert: |<p>This is a caution with some whitespace before the alert type.</p>|alert|",
|
||||
"Blockquote: |<p>A regular blockquote.</p>|regular|",
|
||||
"Blockquote: |<p>A regular blockquote.</p>\n|regular|",
|
||||
"Blockquote Alert Attributes: |<p>This is a tip with attributes.</p>|map[class:foo bar id:baz]|",
|
||||
filepath.FromSlash("/content/p1.md:19:3"),
|
||||
"Blockquote Alert Page: |<p>This is a tip with attributes.</p>|p1|p1|",
|
||||
@@ -248,6 +249,37 @@ title: home
|
||||
"AlertType: fourteen|AlertTitle: title|Text: <p><img src=\"a.jpg\" alt=\"alt\"></p>|",
|
||||
"AlertType: fifteen|AlertTitle: <em>title</em>|Text: |",
|
||||
"AlertType: sixteen|AlertTitle: <em>title</em>|Text: <p>line one</p>|",
|
||||
"AlertType: |AlertTitle: |Text: <p>seventeen</p>|",
|
||||
"AlertType: |AlertTitle: |Text: <p>seventeen</p>\n|",
|
||||
)
|
||||
}
|
||||
|
||||
// Issue14046
|
||||
func TestBlockquoteDefaultOutput(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
disableKinds = ['home','rss','section','sitemap','taxonomy','term']
|
||||
-- content/p1.md --
|
||||
---
|
||||
title: p1
|
||||
---
|
||||
> foo
|
||||
-- layouts/page.html --
|
||||
|{{ .Content }}|
|
||||
-- xxx --
|
||||
<blockquote>
|
||||
{{ .Text }}
|
||||
</blockquote>
|
||||
`
|
||||
|
||||
want := "|<blockquote>\n<p>foo</p>\n</blockquote>\n|"
|
||||
|
||||
b := hugolib.Test(t, files)
|
||||
b.AssertFileContent("public/p1/index.html", want) // fail
|
||||
|
||||
files = strings.ReplaceAll(files, "xxx", "layouts/_markup/render-blockquote.html")
|
||||
|
||||
b = hugolib.Test(t, files)
|
||||
b.AssertFileContent("public/p1/index.html", want)
|
||||
}
|
||||
|
||||
@@ -176,8 +176,18 @@ func newMarkdown(pcfg converter.ProviderConfig) goldmark.Markdown {
|
||||
extensions = append(extensions, extension.DefinitionList)
|
||||
}
|
||||
|
||||
if cfg.Extensions.Footnote {
|
||||
extensions = append(extensions, extension.Footnote)
|
||||
if cfg.Extensions.Footnote.Enable {
|
||||
opts := []extension.FootnoteOption{}
|
||||
opts = append(opts, extension.WithFootnoteBacklinkHTML(cfg.Extensions.Footnote.BacklinkHTML))
|
||||
if cfg.Extensions.Footnote.EnableAutoIDPrefix {
|
||||
opts = append(opts,
|
||||
extension.WithFootnoteIDPrefixFunction(func(n ast.Node) []byte {
|
||||
documentID := n.OwnerDocument().Meta()["documentID"].(string)
|
||||
return []byte("h" + documentID)
|
||||
}))
|
||||
}
|
||||
f := extension.NewFootnote(opts...)
|
||||
extensions = append(extensions, f)
|
||||
}
|
||||
|
||||
if cfg.Extensions.CJK.Enable {
|
||||
@@ -262,6 +272,7 @@ func (c *goldmarkConverter) Parse(ctx converter.RenderContext) (converter.Result
|
||||
reader,
|
||||
parser.WithContext(pctx),
|
||||
)
|
||||
doc.OwnerDocument().AddMeta("documentID", c.ctx.DocumentID)
|
||||
|
||||
return parserResult{
|
||||
doc: doc,
|
||||
|
||||
@@ -40,7 +40,11 @@ var Default = Config{
|
||||
RightAngleQuote: "»",
|
||||
Apostrophe: "’",
|
||||
},
|
||||
Footnote: true,
|
||||
Footnote: Footnote{
|
||||
Enable: true,
|
||||
EnableAutoIDPrefix: false,
|
||||
BacklinkHTML: "↩︎",
|
||||
},
|
||||
DefinitionList: true,
|
||||
Table: true,
|
||||
Strikethrough: true,
|
||||
@@ -152,7 +156,7 @@ type LinkRenderHook struct {
|
||||
|
||||
type Extensions struct {
|
||||
Typographer Typographer
|
||||
Footnote bool
|
||||
Footnote Footnote
|
||||
DefinitionList bool
|
||||
Extras Extras
|
||||
Passthrough Passthrough
|
||||
@@ -166,6 +170,13 @@ type Extensions struct {
|
||||
CJK CJK
|
||||
}
|
||||
|
||||
// Footnote holds footnote configuration.
|
||||
type Footnote struct {
|
||||
Enable bool
|
||||
EnableAutoIDPrefix bool
|
||||
BacklinkHTML string
|
||||
}
|
||||
|
||||
// Typographer holds typographer configuration.
|
||||
type Typographer struct {
|
||||
// Whether to disable typographer.
|
||||
|
||||
@@ -897,7 +897,7 @@ title: "p1"
|
||||
---
|
||||
# HTML comments
|
||||
|
||||
## Simple
|
||||
## Simple
|
||||
<!-- This is a comment -->
|
||||
|
||||
<!-- This is a comment indented -->
|
||||
@@ -918,7 +918,7 @@ title: "p1"
|
||||
<img border="0" src="pic_trulli.jpg" alt="Trulli">
|
||||
-->
|
||||
|
||||
## XSS
|
||||
## XSS
|
||||
|
||||
<!-- --><script>alert("I just escaped the HTML comment")</script><!-- -->
|
||||
|
||||
@@ -931,10 +931,10 @@ This is a <!-- hidden--> word.
|
||||
|
||||
This is a <!-- hidden --> word.
|
||||
|
||||
This is a <!--
|
||||
This is a <!--
|
||||
hidden --> word.
|
||||
|
||||
This is a <!--
|
||||
This is a <!--
|
||||
hidden
|
||||
--> word.
|
||||
|
||||
@@ -961,3 +961,83 @@ hidden
|
||||
)
|
||||
b.AssertLogContains("! WARN")
|
||||
}
|
||||
|
||||
func TestFootnoteExtension(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
disableKinds = ['home','rss','section','sitemap','taxonomy','term']
|
||||
[markup.goldmark.extensions.footnote]
|
||||
enable = false
|
||||
enableAutoIDPrefix = false
|
||||
TBD = 'back'
|
||||
-- layouts/all.html --
|
||||
{{ .Content }}
|
||||
-- content/p1.md --
|
||||
---
|
||||
title: p1
|
||||
---
|
||||
foo[^1] and bar[^2]
|
||||
|
||||
[^1]: footnote one
|
||||
[^2]: footnote two
|
||||
-- content/p2.md --
|
||||
---
|
||||
title: p2
|
||||
---
|
||||
foo[^1] and bar[^2]
|
||||
|
||||
[^1]: footnote one
|
||||
[^2]: footnote two
|
||||
-- content/_content.gotmpl --
|
||||
{{ range slice 3 4 }}
|
||||
{{ $page := dict
|
||||
"content" (dict "mediaType" "text/markdown" "value" "foo[^1] and bar[^2]\n\n[^1]: footnote one\n[^2]: footnote two")
|
||||
"path" (printf "p%d" .)
|
||||
"title" (printf "p%d" .)
|
||||
}}
|
||||
{{ $.AddPage $page }}
|
||||
{{ end }}
|
||||
`
|
||||
|
||||
// test enableAutoIDPrefix
|
||||
|
||||
want := "<p>foo[^1] and bar[^2]</p>\n<p>[^1]: footnote one\n[^2]: footnote two</p>"
|
||||
b := hugolib.Test(t, files)
|
||||
b.AssertFileContent("public/p1/index.html", want)
|
||||
b.AssertFileContent("public/p2/index.html", want)
|
||||
b.AssertFileContent("public/p3/index.html", want)
|
||||
b.AssertFileContent("public/p4/index.html", want)
|
||||
|
||||
files = strings.ReplaceAll(files, "enable = false", "enable = true")
|
||||
want = "<p>foo<sup id=\"fnref:1\"><a href=\"#fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> and bar<sup id=\"fnref:2\"><a href=\"#fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup></p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"fn:1\">\n<p>footnote one <a href=\"#fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"fn:2\">\n<p>footnote two <a href=\"#fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>"
|
||||
b = hugolib.Test(t, files)
|
||||
b.AssertFileContent("public/p1/index.html", want)
|
||||
b.AssertFileContent("public/p2/index.html", want)
|
||||
b.AssertFileContent("public/p3/index.html", want)
|
||||
b.AssertFileContent("public/p4/index.html", want)
|
||||
|
||||
files = strings.ReplaceAll(files, "enableAutoIDPrefix = false", "enableAutoIDPrefix = true")
|
||||
b = hugolib.Test(t, files)
|
||||
b.AssertFileContent("public/p1/index.html",
|
||||
"<p>foo<sup id=\"hb5cdcabc9e678612fnref:1\"><a href=\"#hb5cdcabc9e678612fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> and bar<sup id=\"hb5cdcabc9e678612fnref:2\"><a href=\"#hb5cdcabc9e678612fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup></p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"hb5cdcabc9e678612fn:1\">\n<p>footnote one <a href=\"#hb5cdcabc9e678612fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"hb5cdcabc9e678612fn:2\">\n<p>footnote two <a href=\"#hb5cdcabc9e678612fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>",
|
||||
)
|
||||
b.AssertFileContent("public/p2/index.html",
|
||||
"<p>foo<sup id=\"h58e8265a0c07b195fnref:1\"><a href=\"#h58e8265a0c07b195fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> and bar<sup id=\"h58e8265a0c07b195fnref:2\"><a href=\"#h58e8265a0c07b195fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup></p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"h58e8265a0c07b195fn:1\">\n<p>footnote one <a href=\"#h58e8265a0c07b195fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"h58e8265a0c07b195fn:2\">\n<p>footnote two <a href=\"#h58e8265a0c07b195fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>",
|
||||
)
|
||||
b.AssertFileContent("public/p3/index.html",
|
||||
"<p>foo<sup id=\"h0aab769290d7e233fnref:1\"><a href=\"#h0aab769290d7e233fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> and bar<sup id=\"h0aab769290d7e233fnref:2\"><a href=\"#h0aab769290d7e233fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup></p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"h0aab769290d7e233fn:1\">\n<p>footnote one <a href=\"#h0aab769290d7e233fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"h0aab769290d7e233fn:2\">\n<p>footnote two <a href=\"#h0aab769290d7e233fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>",
|
||||
)
|
||||
b.AssertFileContent("public/p4/index.html",
|
||||
"<p>foo<sup id=\"ha35b794ad6e8626cfnref:1\"><a href=\"#ha35b794ad6e8626cfn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> and bar<sup id=\"ha35b794ad6e8626cfnref:2\"><a href=\"#ha35b794ad6e8626cfn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup></p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"ha35b794ad6e8626cfn:1\">\n<p>footnote one <a href=\"#ha35b794ad6e8626cfnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n<li id=\"ha35b794ad6e8626cfn:2\">\n<p>footnote two <a href=\"#ha35b794ad6e8626cfnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">↩︎</a></p>\n</li>\n</ol>\n</div>",
|
||||
)
|
||||
|
||||
// test backlinkHTML
|
||||
|
||||
files = strings.ReplaceAll(files, "TBD", "backlinkHTML")
|
||||
b = hugolib.Test(t, files)
|
||||
b.AssertFileContent("public/p1/index.html",
|
||||
"<p>foo<sup id=\"hb5cdcabc9e678612fnref:1\"><a href=\"#hb5cdcabc9e678612fn:1\" class=\"footnote-ref\" role=\"doc-noteref\">1</a></sup> and bar<sup id=\"hb5cdcabc9e678612fnref:2\"><a href=\"#hb5cdcabc9e678612fn:2\" class=\"footnote-ref\" role=\"doc-noteref\">2</a></sup></p>\n<div class=\"footnotes\" role=\"doc-endnotes\">\n<hr>\n<ol>\n<li id=\"hb5cdcabc9e678612fn:1\">\n<p>footnote one <a href=\"#hb5cdcabc9e678612fnref:1\" class=\"footnote-backref\" role=\"doc-backlink\">back</a></p>\n</li>\n<li id=\"hb5cdcabc9e678612fn:2\">\n<p>footnote two <a href=\"#hb5cdcabc9e678612fnref:2\" class=\"footnote-backref\" role=\"doc-backlink\">back</a></p>\n</li>\n</ol>\n</div>",
|
||||
)
|
||||
}
|
||||
|
||||
@@ -86,20 +86,26 @@ func normalizeConfig(m map[string]any) {
|
||||
}
|
||||
}
|
||||
|
||||
// Changed from a bool in 0.112.0.
|
||||
// Handle changes to the Goldmark configuration.
|
||||
v, err = maps.GetNestedParam("goldmark.extensions", ".", m)
|
||||
if err == nil {
|
||||
vm := maps.ToStringMap(v)
|
||||
const typographerKey = "typographer"
|
||||
if vv, found := vm[typographerKey]; found {
|
||||
if vvb, ok := vv.(bool); ok {
|
||||
if !vvb {
|
||||
vm[typographerKey] = goldmark_config.Typographer{
|
||||
Disable: true,
|
||||
}
|
||||
} else {
|
||||
delete(vm, typographerKey)
|
||||
}
|
||||
|
||||
// We changed the typographer extension config from a bool to a struct in 0.112.0.
|
||||
migrateGoldmarkConfig(vm, "typographer", goldmark_config.Typographer{Disable: true})
|
||||
|
||||
// We changed the footnote extension config from a bool to a struct in 0.151.0.
|
||||
migrateGoldmarkConfig(vm, "footnote", goldmark_config.Footnote{Enable: false})
|
||||
}
|
||||
}
|
||||
|
||||
func migrateGoldmarkConfig(vm map[string]any, key string, falseVal any) {
|
||||
if vv, found := vm[key]; found {
|
||||
if vvb, ok := vv.(bool); ok {
|
||||
if !vvb {
|
||||
vm[key] = falseVal
|
||||
} else {
|
||||
delete(vm, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,14 +52,16 @@ func TestConfig(t *testing.T) {
|
||||
c.Assert(conf.AsciidocExt.Extensions[0], qt.Equals, "asciidoctor-html5s")
|
||||
})
|
||||
|
||||
c.Run("Decode legacy typographer", func(c *qt.C) {
|
||||
// We changed the typographer extension config from a bool to a struct in 0.112.0.
|
||||
// We changed the footnote extension config from a bool to a struct in 0.151.0.
|
||||
c.Run("Decode legacy Goldmark configs", func(c *qt.C) {
|
||||
c.Parallel()
|
||||
v := config.New()
|
||||
|
||||
// typographer was changed from a bool to a struct in 0.112.0.
|
||||
v.Set("markup", map[string]any{
|
||||
"goldmark": map[string]any{
|
||||
"extensions": map[string]any{
|
||||
"footnote": false,
|
||||
"typographer": false,
|
||||
},
|
||||
},
|
||||
@@ -68,11 +70,13 @@ func TestConfig(t *testing.T) {
|
||||
conf, err := Decode(v)
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(conf.Goldmark.Extensions.Footnote.Enable, qt.Equals, false)
|
||||
c.Assert(conf.Goldmark.Extensions.Typographer.Disable, qt.Equals, true)
|
||||
|
||||
v.Set("markup", map[string]any{
|
||||
"goldmark": map[string]any{
|
||||
"extensions": map[string]any{
|
||||
"footnote": true,
|
||||
"typographer": true,
|
||||
},
|
||||
},
|
||||
@@ -81,6 +85,7 @@ func TestConfig(t *testing.T) {
|
||||
conf, err = Decode(v)
|
||||
|
||||
c.Assert(err, qt.IsNil)
|
||||
c.Assert(conf.Goldmark.Extensions.Footnote.Enable, qt.Equals, true)
|
||||
c.Assert(conf.Goldmark.Extensions.Typographer.Disable, qt.Equals, false)
|
||||
c.Assert(conf.Goldmark.Extensions.Typographer.Ellipsis, qt.Equals, "…")
|
||||
})
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"fmt"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
"unique"
|
||||
)
|
||||
|
||||
const eof = -1
|
||||
@@ -78,7 +79,7 @@ func newPageLexer(input []byte, stateStart stateFunc, cfg Config) *pageLexer {
|
||||
lexerShortcodeState: lexerShortcodeState{
|
||||
currLeftDelimItem: tLeftDelimScNoMarkup,
|
||||
currRightDelimItem: tRightDelimScNoMarkup,
|
||||
openShortcodes: make(map[string]bool),
|
||||
openShortcodes: make(map[unique.Handle[string]]bool),
|
||||
},
|
||||
items: make([]Item, 0, 5),
|
||||
}
|
||||
|
||||
@@ -13,15 +13,17 @@
|
||||
|
||||
package pageparser
|
||||
|
||||
import "unique"
|
||||
|
||||
type lexerShortcodeState struct {
|
||||
currLeftDelimItem ItemType
|
||||
currRightDelimItem ItemType
|
||||
isInline bool
|
||||
currShortcodeName string // is only set when a shortcode is in opened state
|
||||
closingState int // > 0 = on its way to be closed
|
||||
elementStepNum int // step number in element
|
||||
paramElements int // number of elements (name + value = 2) found first
|
||||
openShortcodes map[string]bool // set of shortcodes in open state
|
||||
currShortcodeName string // is only set when a shortcode is in opened state
|
||||
closingState int // > 0 = on its way to be closed
|
||||
elementStepNum int // step number in element
|
||||
paramElements int // number of elements (name + value = 2) found first
|
||||
openShortcodes map[unique.Handle[string]]bool // set of shortcodes in open state
|
||||
}
|
||||
|
||||
// Shortcode syntax
|
||||
@@ -254,16 +256,17 @@ Loop:
|
||||
}
|
||||
default:
|
||||
l.backup()
|
||||
word := string(l.input[l.start:l.pos])
|
||||
if l.closingState > 0 && !l.openShortcodes[word] {
|
||||
return l.errorf("closing tag for shortcode '%s' does not match start tag", word)
|
||||
} else if l.closingState > 0 {
|
||||
word := unique.Make(string(l.input[l.start:l.pos]))
|
||||
if l.closingState > 0 {
|
||||
if !l.openShortcodes[word] {
|
||||
return l.errorf("closing tag for shortcode '%s' does not match start tag", word.Value())
|
||||
}
|
||||
l.openShortcodes[word] = false
|
||||
lookForEnd = true
|
||||
}
|
||||
|
||||
l.closingState = 0
|
||||
l.currShortcodeName = word
|
||||
l.currShortcodeName = word.Value()
|
||||
l.openShortcodes[word] = true
|
||||
l.elementStepNum++
|
||||
if l.isInline {
|
||||
|
||||
@@ -142,6 +142,12 @@ var shortCodeLexerTests = []lexerTest{
|
||||
tstLeftNoMD, tstSC2, tstRightNoMD,
|
||||
tstLeftNoMD, tstSCClose, tstSC1, tstRightNoMD, tstEOF,
|
||||
}, nil},
|
||||
{"nested same", `{{< sc1 >}}{{< sc1 >}}{{< /sc1 >}}{{< /sc1 >}}`, []typeText{
|
||||
tstLeftNoMD, tstSC1, tstRightNoMD,
|
||||
tstLeftNoMD, tstSC1, tstRightNoMD,
|
||||
tstLeftNoMD, tstSCClose, tstSC1, tstRightNoMD,
|
||||
tstLeftNoMD, tstSCClose, tstSC1, tstRightNoMD, tstEOF,
|
||||
}, nil},
|
||||
{"nested complex", `{{< sc1 >}}ab{{% sc2 param1 %}}cd{{< sc3 >}}ef{{< /sc3 >}}gh{{% /sc2 %}}ij{{< /sc1 >}}kl`, []typeText{
|
||||
tstLeftNoMD, tstSC1, tstRightNoMD,
|
||||
nti(tText, "ab"),
|
||||
|
||||
@@ -111,6 +111,19 @@ func New(rs *resources.Spec) *Client {
|
||||
ShouldCache: func(req *http.Request, resp *http.Response, key string) bool {
|
||||
return shouldCache(resp.StatusCode)
|
||||
},
|
||||
CanStore: func(reqCacheControl, respCacheControl httpcache.CacheControl) (canStore bool) {
|
||||
if httpCacheConfig.Base.RespectCacheControlNoStoreInResponse {
|
||||
if _, ok := respCacheControl["no-store"]; ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if httpCacheConfig.Base.RespectCacheControlNoStoreInRequest {
|
||||
if _, ok := reqCacheControl["no-store"]; ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
},
|
||||
MarkCachedResponses: true,
|
||||
EnableETagPair: true,
|
||||
Transport: &transport{
|
||||
|
||||
@@ -220,6 +220,8 @@ func (c *Client) FromRemote(uri string, optionsm map[string]any) (resource.Resou
|
||||
|
||||
if res.StatusCode == http.StatusNotFound {
|
||||
// Not found. This matches how lookups for local resources work.
|
||||
// To cache this, we need to make sure the body is read.
|
||||
io.Copy(io.Discard, res.Body)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ apps:
|
||||
plugs:
|
||||
- home
|
||||
- network-bind
|
||||
- desktop
|
||||
- removable-media
|
||||
- etc-gitconfig
|
||||
- gitconfig
|
||||
|
||||
@@ -20,7 +20,7 @@ stderr 'invalid style: __invalid_style__'
|
||||
hugo gen chromastyles --style monokai
|
||||
! stdout '{ }'
|
||||
hugo gen chromastyles --omitEmpty --style monokai --logLevel info
|
||||
stderr 'INFO deprecated: --omitEmpty was deprecated'
|
||||
stderr 'deprecated: --omitEmpty was deprecated'
|
||||
|
||||
# Disable class comments.
|
||||
hugo gen chromastyles --style monokai
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
hugo --minify --logLevel=info
|
||||
|
||||
! stderr 'deprecated'
|
||||
grep '<p>one</p><p>two</p>' public/index.html
|
||||
|
||||
-- hugo.toml --
|
||||
disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
||||
-- content/_index.md --
|
||||
one
|
||||
|
||||
two
|
||||
-- layouts/all.html --
|
||||
{{ .Content }}
|
||||
@@ -0,0 +1,39 @@
|
||||
hugo --quiet
|
||||
ls public/files
|
||||
stdout 'f1.txt'
|
||||
stdout 'f2.txt'
|
||||
|
||||
grep 'enf1' public/files/f1.txt # en mount is last.
|
||||
grep 'frf2' public/files/f2.txt
|
||||
|
||||
-- hugo.toml --
|
||||
disableKinds = ["taxonomy", "term"]
|
||||
defaultContentLanguage = "en"
|
||||
defaultContentLanguageInSubdir = true
|
||||
|
||||
[languages]
|
||||
[languages.en]
|
||||
languageName = "English"
|
||||
weight = 1
|
||||
[languages.fr]
|
||||
languageName = "Français"
|
||||
weight = 2
|
||||
[module]
|
||||
[[module.mounts]]
|
||||
source = "static/fr"
|
||||
target = "static"
|
||||
lang = "fr"
|
||||
[[module.mounts]]
|
||||
source = "static/en"
|
||||
target = "static"
|
||||
lang = "en"
|
||||
|
||||
-- static/en/files/f1.txt --
|
||||
enf1
|
||||
-- static/fr/files/f1.txt --
|
||||
frf1
|
||||
-- static/fr/files/f2.txt --
|
||||
frf2
|
||||
-- layouts/home.html --
|
||||
Home.
|
||||
|
||||
@@ -24,6 +24,7 @@ myenv = "theproduction"
|
||||
-- config/development/params.toml --
|
||||
myenv = "thedevelopment"
|
||||
-- layouts/index.html --
|
||||
<!DOCTYPE html>
|
||||
<body>
|
||||
Title: {{ .Title }}|BaseURL: {{ site.BaseURL }}|ServerPort: {{ site.ServerPort }}|myenv: {{ .Site.Params.myenv }}|Env: {{ hugo.Environment }}|IsServer: {{ hugo.IsServer }}|
|
||||
</body>
|
||||
|
||||
@@ -5,9 +5,14 @@ hugo server --renderToMemory &
|
||||
|
||||
waitServer
|
||||
|
||||
# Assert home page.
|
||||
httpget $HUGOTEST_BASEURL_0 'Title: Hugo Server Test' $HUGOTEST_BASEURL_0
|
||||
httpget $HUGOTEST_BASEURL_1 'Title: Hugo Serveur Test' $HUGOTEST_BASEURL_1
|
||||
|
||||
# Assert static mount.
|
||||
httpget ${HUGOTEST_BASEURL_0}mystatic/mytext.txt 'en_mytext'
|
||||
httpget ${HUGOTEST_BASEURL_1}mystatic/mytext.txt 'fr_mytext'
|
||||
|
||||
stopServer
|
||||
! stderr .
|
||||
|
||||
@@ -15,6 +20,16 @@ stopServer
|
||||
title = "Hugo Server Test"
|
||||
baseURL = "https://example.org/"
|
||||
disableKinds = ["taxonomy", "term", "sitemap"]
|
||||
|
||||
[[module.mounts]]
|
||||
source = 'static/en'
|
||||
target = 'static'
|
||||
lang = 'en'
|
||||
[[module.mounts]]
|
||||
source = 'static/fr'
|
||||
target = 'static'
|
||||
lang = 'fr'
|
||||
|
||||
[languages]
|
||||
[languages.en]
|
||||
baseURL = "https://en.example.org/"
|
||||
@@ -28,5 +43,9 @@ languageName = "Français"
|
||||
weight = 2
|
||||
-- layouts/index.html --
|
||||
Title: {{ .Title }}|BaseURL: {{ site.BaseURL }}|
|
||||
-- static/en/mystatic/mytext.txt --
|
||||
en_mytext
|
||||
-- static/fr/mystatic/mytext.txt --
|
||||
fr_mytext
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ hugo server --renderToMemory --renderStaticToDisk &
|
||||
|
||||
waitServer
|
||||
|
||||
httpget $HUGOTEST_BASEURL_0 'Title: Hugo Server Test' $HUGOTEST_BASEURL_0
|
||||
httpget ${HUGOTEST_BASEURL_0}mystatic.txt 'This is a static file.'
|
||||
httpget ${HUGOTEST_BASEURL_0}en/ 'Title: Hugo Server Test' $HUGOTEST_BASEURL_0
|
||||
httpget ${HUGOTEST_BASEURL_0}mystatic.txt 'This is a static file in English.'
|
||||
|
||||
! exists public/index.html
|
||||
exists public/mystatic.txt
|
||||
@@ -18,8 +18,32 @@ stopServer
|
||||
title = "Hugo Server Test"
|
||||
baseURL = "https://example.org/"
|
||||
disableKinds = ["taxonomy", "term", "sitemap"]
|
||||
-- static/mystatic.txt --
|
||||
This is a static file.
|
||||
defaultContentLanguage = "en"
|
||||
defaultContentLanguageInSubdir = true
|
||||
[[module.mounts]]
|
||||
source = 'static/en'
|
||||
target = 'static'
|
||||
lang = 'en'
|
||||
[[module.mounts]]
|
||||
source = 'static/fr'
|
||||
target = 'static'
|
||||
lang = 'fr'
|
||||
|
||||
|
||||
[languages]
|
||||
[languages.en]
|
||||
languageName = "English"
|
||||
title = "Hugo Server Test"
|
||||
weight = 1
|
||||
[languages.fr]
|
||||
title = "Hugo Serveur Test"
|
||||
languageName = "Français"
|
||||
weight = 2
|
||||
|
||||
-- static/en/mystatic.txt --
|
||||
This is a static file in English.
|
||||
-- static/en/mystatic.txt --
|
||||
This is a static file in English.
|
||||
-- layouts/index.html --
|
||||
Title: {{ .Title }}|BaseURL: {{ site.BaseURL }}|
|
||||
|
||||
|
||||
+10
-2
@@ -15,6 +15,7 @@ package math
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
|
||||
"github.com/gohugoio/hugo/deps"
|
||||
"github.com/gohugoio/hugo/tpl/internal"
|
||||
@@ -23,6 +24,13 @@ import (
|
||||
const name = "math"
|
||||
|
||||
func init() {
|
||||
mathAtan1 := "0.7853981633974483"
|
||||
mathTan1 := "1.557407724654902"
|
||||
if runtime.GOARCH == "s390x" {
|
||||
mathAtan1 = "0.7853981633974484"
|
||||
mathTan1 = "1.5574077246549018"
|
||||
}
|
||||
|
||||
f := func(d *deps.Deps) *internal.TemplateFuncsNamespace {
|
||||
ctx := New(d)
|
||||
|
||||
@@ -62,7 +70,7 @@ func init() {
|
||||
ns.AddMethodMapping(ctx.Atan,
|
||||
nil,
|
||||
[][2]string{
|
||||
{"{{ math.Atan 1 }}", "0.7853981633974483"},
|
||||
{"{{ math.Atan 1 }}", mathAtan1},
|
||||
},
|
||||
)
|
||||
|
||||
@@ -202,7 +210,7 @@ func init() {
|
||||
ns.AddMethodMapping(ctx.Tan,
|
||||
nil,
|
||||
[][2]string{
|
||||
{"{{ math.Tan 1 }}", "1.557407724654902"},
|
||||
{"{{ math.Tan 1 }}", mathTan1},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -111,7 +111,11 @@ func (ns *Namespace) Truncate(s any, options ...any) (template.HTML, error) {
|
||||
if unicode.IsSpace(r) {
|
||||
lastWordIndex = lastNonSpace
|
||||
} else if unicode.In(r, unicode.Han, unicode.Hangul, unicode.Hiragana, unicode.Katakana) {
|
||||
lastWordIndex = i
|
||||
lastWordIndex = lastNonSpace
|
||||
lastNonSpace = i + utf8.RuneLen(r)
|
||||
if currentLen <= length {
|
||||
lastWordIndex = lastNonSpace
|
||||
}
|
||||
} else {
|
||||
lastNonSpace = i + utf8.RuneLen(r)
|
||||
}
|
||||
|
||||
@@ -41,6 +41,19 @@ func TestTruncate(t *testing.T) {
|
||||
{10, template.HTML("<p>IamanextremelylongwordthatjustgoesonandonandonjusttoannoyyoualmostasifIwaswritteninGermanActuallyIbettheresagermanwordforthis</p>"), nil, template.HTML("<p>Iamanextre …</p>"), false},
|
||||
{13, template.HTML("With <a href=\"/markdown\">Markdown</a> inside."), nil, template.HTML("With <a href=\"/markdown\">Markdown …</a>"), false},
|
||||
{14, "Hello中国 Good 好的", nil, template.HTML("Hello中国 Good 好 …"), false},
|
||||
{12, "", "日本語でHugoを使います", template.HTML("日本語でHugoを使いま"), false},
|
||||
{12, "", "日本語で Hugo を使います", template.HTML("日本語で Hugo を使"), false},
|
||||
{8, "", "日本語でHugoを使います", template.HTML("日本語でHugo"), false},
|
||||
{10, "", "日本語で Hugo を使います", template.HTML("日本語で Hugo"), false},
|
||||
{9, "", "日本語で Hugo を使います", template.HTML("日本語で Hugo"), false},
|
||||
{7, "", "日本語でHugoを使います", template.HTML("日本語で"), false},
|
||||
{7, "", "日本語で Hugo を使います", template.HTML("日本語で"), false},
|
||||
{6, "", "日本語でHugoを使います", template.HTML("日本語で"), false},
|
||||
{6, "", "日本語で Hugo を使います", template.HTML("日本語で"), false},
|
||||
{5, "", "日本語でHugoを使います", template.HTML("日本語で"), false},
|
||||
{5, "", "日本語で Hugo を使います", template.HTML("日本語で"), false},
|
||||
{4, "", "日本語でHugoを使います", template.HTML("日本語で"), false},
|
||||
{4, "", "日本語で Hugo を使います", template.HTML("日本語で"), false},
|
||||
{15, "", template.HTML("A <br> tag that's not closed"), template.HTML("A <br> tag that's"), false},
|
||||
{14, template.HTML("<p>Hello中国 Good 好的</p>"), nil, template.HTML("<p>Hello中国 Good 好 …</p>"), false},
|
||||
{2, template.HTML("<p>P1</p><p>P2</p>"), nil, template.HTML("<p>P1 …</p>"), false},
|
||||
|
||||
@@ -27,6 +27,11 @@ import (
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
|
||||
htmltomarkdown "github.com/JohannesKaufmann/html-to-markdown/v2/converter"
|
||||
"github.com/JohannesKaufmann/html-to-markdown/v2/plugin/base"
|
||||
"github.com/JohannesKaufmann/html-to-markdown/v2/plugin/commonmark"
|
||||
"github.com/JohannesKaufmann/html-to-markdown/v2/plugin/table"
|
||||
|
||||
bp "github.com/gohugoio/hugo/bufferpool"
|
||||
|
||||
"github.com/bep/goportabletext"
|
||||
@@ -324,3 +329,32 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, er
|
||||
func (ns *Namespace) Reset() {
|
||||
ns.cacheUnmarshal.Clear()
|
||||
}
|
||||
|
||||
// This was added in Hugo v0.151.0 and should be considered experimental for now.
|
||||
// We need to test this out in the wild for a while before committing to this API,
|
||||
// and there will eventually be more options here.
|
||||
func (ns *Namespace) HTMLToMarkdown(ctx context.Context, args ...any) (string, error) {
|
||||
if len(args) < 1 {
|
||||
return "", errors.New("must provide at least one argument")
|
||||
}
|
||||
input, err := cast.ToStringE(args[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
plugins := []htmltomarkdown.Plugin{
|
||||
base.NewBasePlugin(),
|
||||
commonmark.NewCommonmarkPlugin(),
|
||||
table.NewTablePlugin(),
|
||||
}
|
||||
|
||||
conv := htmltomarkdown.NewConverter(
|
||||
htmltomarkdown.WithPlugins(plugins...),
|
||||
)
|
||||
|
||||
markdown, err := conv.ConvertString(input)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return markdown, nil
|
||||
}
|
||||
|
||||
@@ -535,3 +535,59 @@ disableKinds = ['page','rss','section','sitemap','taxonomy','term']
|
||||
b, err = hugolib.TestE(t, f)
|
||||
b.Assert(err.Error(), qt.Contains, "invalid strict mode")
|
||||
}
|
||||
|
||||
func TestHTMLToMarkdown(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
markdown := `
|
||||
# Heading
|
||||
|
||||
Some **bold** text.
|
||||
|
||||
A [link](https://example.com).
|
||||
|
||||
An image:
|
||||
|
||||

|
||||
|
||||
A list:
|
||||
|
||||
- Item 1
|
||||
- Item 2
|
||||
- Item 2a
|
||||
- Item 2b
|
||||
|
||||
A table:
|
||||
|
||||
| Header 1 | Header 2 |
|
||||
|----------|----------|
|
||||
| Cell 1 | Cell 2 |
|
||||
| Cell 3 | Cell 4 |
|
||||
|
||||
A blockquote:
|
||||
|
||||
> This is a quote.
|
||||
`
|
||||
files := `
|
||||
-- hugo.toml --
|
||||
disableKinds = ['rss','section','sitemap','taxonomy','term']
|
||||
-- layouts/all.html --
|
||||
All html.
|
||||
-- layouts/all.markdown --
|
||||
{{ .Content | transform.HTMLToMarkdown | safeHTML }}
|
||||
-- content/p1.md --
|
||||
---
|
||||
title: p1
|
||||
outputs: ["html", "markdown"]
|
||||
---
|
||||
`
|
||||
|
||||
files += markdown
|
||||
|
||||
b := hugolib.Test(t, files)
|
||||
|
||||
b.AssertFileContent("public/p1/index.html", `All html.`)
|
||||
|
||||
// There are some white space differences, so we cannot do an exact match.
|
||||
b.AssertFileContent("public/p1/index.md", markdown)
|
||||
}
|
||||
|
||||
@@ -49,6 +49,15 @@ func New(baseURL *url.URL) transform.Transformer {
|
||||
idx += len(ignoredSyntax.Find(b[idx:]))
|
||||
idx += len(tag.Find(b[idx:]))
|
||||
}
|
||||
if idx == 0 {
|
||||
// doctype is required for HTML5, we did not find it,
|
||||
// and neither did we find html or head tags, so
|
||||
// skip injection.
|
||||
// This allows us to render partial HTML documents to be used in
|
||||
// e.g. JS frameworks.
|
||||
ft.To().Write(b)
|
||||
return nil
|
||||
}
|
||||
|
||||
path := strings.TrimSuffix(baseURL.Path, "/")
|
||||
|
||||
|
||||
@@ -59,12 +59,12 @@ func TestLiveReloadInject(t *testing.T) {
|
||||
c.Assert(apply("<!doctype html>after"), qt.Equals, "<!doctype html>"+expectBase+"after")
|
||||
})
|
||||
|
||||
c.Run("Inject before other elements if all else omitted", func(c *qt.C) {
|
||||
c.Assert(apply("<title>after</title>"), qt.Equals, expectBase+"<title>after</title>")
|
||||
c.Run("Inject nothing if no doctype, html or head found", func(c *qt.C) {
|
||||
c.Assert(apply("<title>after</title>"), qt.Equals, "<title>after</title>")
|
||||
})
|
||||
|
||||
c.Run("Inject before text content if all else omitted", func(c *qt.C) {
|
||||
c.Assert(apply("after"), qt.Equals, expectBase+"after")
|
||||
c.Run("Inject nothing if no tag found", func(c *qt.C) {
|
||||
c.Assert(apply("after"), qt.Equals, "after")
|
||||
})
|
||||
|
||||
c.Run("Inject after HeAd tag MiXed CaSe", func(c *qt.C) {
|
||||
|
||||
Reference in New Issue
Block a user