Compare commits

..

No commits in common. "master" and "v0.147.3" have entirely different histories.

73 changed files with 574 additions and 1724 deletions

View file

@ -2,8 +2,8 @@
# Twitter: https://twitter.com/gohugoio
# Website: https://gohugo.io/
ARG GO_VERSION="1.24"
ARG ALPINE_VERSION="3.22"
ARG GO_VERSION="1.23.2"
ARG ALPINE_VERSION="3.20"
ARG DART_SASS_VERSION="1.79.3"
FROM --platform=$BUILDPLATFORM tonistiigi/xx:1.5.0 AS xx
@ -19,7 +19,7 @@ RUN apk add clang lld
COPY --from=xx / /
ARG TARGETPLATFORM
RUN xx-apk add musl-dev gcc g++
RUN xx-apk add musl-dev gcc g++
# Optionally set HUGO_BUILD_TAGS to "none" or "withdeploy" when building like so:
# docker build --build-arg HUGO_BUILD_TAGS=withdeploy .
@ -72,7 +72,7 @@ RUN mkdir -p /var/hugo/bin /cache && \
adduser -Sg hugo -u 1000 -h /var/hugo hugo && \
chown -R hugo: /var/hugo /cache && \
# For the Hugo's Git integration to work.
runuser -u hugo -- git config --global --add safe.directory /project && \
runuser -u hugo -- git config --global --add safe.directory /project && \
# See https://github.com/gohugoio/hugo/issues/9810
runuser -u hugo -- git config --global core.quotepath false

View file

@ -972,9 +972,6 @@ func (c *hugoBuilder) handleEvents(watcher *watcher.Batcher,
lrl.Logf("force refresh")
livereload.ForceRefresh()
}
} else {
lrl.Logf("force refresh")
livereload.ForceRefresh()
}
if len(cssChanges) > 0 {

View file

@ -15,7 +15,6 @@ package collections
import (
"html/template"
"reflect"
"testing"
qt "github.com/frankban/quicktest"
@ -78,7 +77,6 @@ func TestAppend(t *testing.T) {
{[]string{"a", "b"}, []any{nil}, []any{"a", "b", nil}},
{[]string{"a", "b"}, []any{nil, "d", nil}, []any{"a", "b", nil, "d", nil}},
{[]any{"a", nil, "c"}, []any{"d", nil, "f"}, []any{"a", nil, "c", "d", nil, "f"}},
{[]string{"a", "b"}, []any{}, []string{"a", "b"}},
} {
result, err := Append(test.start, test.addend...)
@ -148,66 +146,3 @@ func TestAppendShouldMakeACopyOfTheInputSlice(t *testing.T) {
c.Assert(result, qt.DeepEquals, []string{"a", "b", "c"})
c.Assert(slice, qt.DeepEquals, []string{"d", "b"})
}
func TestIndirect(t *testing.T) {
t.Parallel()
c := qt.New(t)
type testStruct struct {
Field string
}
var (
nilPtr *testStruct
nilIface interface{} = nil
nonNilIface interface{} = &testStruct{Field: "hello"}
)
tests := []struct {
name string
input any
wantKind reflect.Kind
wantNil bool
}{
{
name: "nil pointer",
input: nilPtr,
wantKind: reflect.Ptr,
wantNil: true,
},
{
name: "nil interface",
input: nilIface,
wantKind: reflect.Invalid,
wantNil: false,
},
{
name: "non-nil pointer to struct",
input: &testStruct{Field: "abc"},
wantKind: reflect.Struct,
wantNil: false,
},
{
name: "non-nil interface holding pointer",
input: nonNilIface,
wantKind: reflect.Struct,
wantNil: false,
},
{
name: "plain value",
input: testStruct{Field: "xyz"},
wantKind: reflect.Struct,
wantNil: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
v := reflect.ValueOf(tt.input)
got, isNil := indirect(v)
c.Assert(got.Kind(), qt.Equals, tt.wantKind)
c.Assert(isNil, qt.Equals, tt.wantNil)
})
}
}

View file

@ -136,37 +136,3 @@ func TestSortedStringSlice(t *testing.T) {
c.Assert(s.Count("z"), qt.Equals, 0)
c.Assert(s.Count("a"), qt.Equals, 1)
}
func TestStringSliceToInterfaceSlice(t *testing.T) {
t.Parallel()
c := qt.New(t)
tests := []struct {
name string
in []string
want []any
}{
{
name: "empty slice",
in: []string{},
want: []any{},
},
{
name: "single element",
in: []string{"hello"},
want: []any{"hello"},
},
{
name: "multiple elements",
in: []string{"a", "b", "c"},
want: []any{"a", "b", "c"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := StringSliceToInterfaceSlice(tt.in)
c.Assert(got, qt.DeepEquals, tt.want)
})
}
}

View file

@ -1,77 +0,0 @@
package collections
import (
"testing"
qt "github.com/frankban/quicktest"
)
func TestNewStack(t *testing.T) {
t.Parallel()
c := qt.New(t)
s := NewStack[int]()
c.Assert(s, qt.IsNotNil)
}
func TestStackBasic(t *testing.T) {
t.Parallel()
c := qt.New(t)
s := NewStack[int]()
c.Assert(s.Len(), qt.Equals, 0)
s.Push(1)
s.Push(2)
s.Push(3)
c.Assert(s.Len(), qt.Equals, 3)
top, ok := s.Peek()
c.Assert(ok, qt.Equals, true)
c.Assert(top, qt.Equals, 3)
popped, ok := s.Pop()
c.Assert(ok, qt.Equals, true)
c.Assert(popped, qt.Equals, 3)
c.Assert(s.Len(), qt.Equals, 2)
_, _ = s.Pop()
_, _ = s.Pop()
_, ok = s.Pop()
c.Assert(ok, qt.Equals, false)
}
func TestStackDrain(t *testing.T) {
t.Parallel()
c := qt.New(t)
s := NewStack[string]()
s.Push("a")
s.Push("b")
got := s.Drain()
c.Assert(got, qt.DeepEquals, []string{"a", "b"})
c.Assert(s.Len(), qt.Equals, 0)
}
func TestStackDrainMatching(t *testing.T) {
t.Parallel()
c := qt.New(t)
s := NewStack[int]()
s.Push(1)
s.Push(2)
s.Push(3)
s.Push(4)
got := s.DrainMatching(func(v int) bool { return v%2 == 0 })
c.Assert(got, qt.DeepEquals, []int{4, 2})
c.Assert(s.Drain(), qt.DeepEquals, []int{1, 3})
}

View file

@ -24,7 +24,6 @@ const (
WarnRenderShortcodesInHTML = "warning-rendershortcodes-in-html"
WarnGoldmarkRawHTML = "warning-goldmark-raw-html"
WarnPartialSuperfluousPrefix = "warning-partial-superfluous-prefix"
WarnHomePageIsLeafBundle = "warning-home-page-is-leaf-bundle"
)
// Field/method names with special meaning.

View file

@ -17,7 +17,7 @@ package hugo
// This should be the only one.
var CurrentVersion = Version{
Major: 0,
Minor: 148,
PatchLevel: 0,
Suffix: "-DEV",
Minor: 147,
PatchLevel: 3,
Suffix: "",
}

View file

@ -120,20 +120,15 @@ func (pp *PathParser) parse(component, s string) (*Path, error) {
return p, nil
}
func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot, numDots int, isLast bool) {
func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot int) {
if p.posContainerHigh != -1 {
return
}
mayHaveLang := numDots > 1 && p.posIdentifierLanguage == -1 && pp.LanguageIndex != nil
mayHaveLang := p.posIdentifierLanguage == -1 && pp.LanguageIndex != nil
mayHaveLang = mayHaveLang && (component == files.ComponentFolderContent || component == files.ComponentFolderLayouts)
mayHaveOutputFormat := component == files.ComponentFolderLayouts
mayHaveKind := p.posIdentifierKind == -1 && mayHaveOutputFormat
var mayHaveLayout bool
if p.pathType == TypeShortcode {
mayHaveLayout = !isLast && component == files.ComponentFolderLayouts
} else {
mayHaveLayout = component == files.ComponentFolderLayouts
}
mayHaveLayout := component == files.ComponentFolderLayouts
var found bool
var high int
@ -172,6 +167,7 @@ func (pp *PathParser) parseIdentifier(component, s string, p *Path, i, lastDot,
if langFound {
p.identifiersKnown = append(p.identifiersKnown, id)
p.posIdentifierLanguage = len(p.identifiersKnown) - 1
}
}
@ -238,24 +234,19 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
p.s = s
slashCount := 0
lastDot := 0
lastSlashIdx := strings.LastIndex(s, "/")
numDots := strings.Count(s[lastSlashIdx+1:], ".")
if strings.Contains(s, "/_shortcodes/") {
p.pathType = TypeShortcode
}
for i := len(s) - 1; i >= 0; i-- {
c := s[i]
switch c {
case '.':
pp.parseIdentifier(component, s, p, i, lastDot, numDots, false)
pp.parseIdentifier(component, s, p, i, lastDot)
lastDot = i
case '/':
slashCount++
if p.posContainerHigh == -1 {
if lastDot > 0 {
pp.parseIdentifier(component, s, p, i, lastDot, numDots, true)
pp.parseIdentifier(component, s, p, i, lastDot)
}
p.posContainerHigh = i + 1
} else if p.posContainerLow == -1 {
@ -291,9 +282,10 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
p.pathType = TypeContentData
}
}
}
if p.pathType < TypeMarkup && component == files.ComponentFolderLayouts {
if component == files.ComponentFolderLayouts {
if p.posIdentifierBaseof != -1 {
p.pathType = TypeBaseof
} else {
@ -309,10 +301,12 @@ func (pp *PathParser) doParse(component, s string, p *Path) (*Path, error) {
}
if p.pathType == TypeShortcode && p.posIdentifierLayout != -1 {
id := p.identifiersKnown[p.posIdentifierLayout]
if id.Low == p.posContainerHigh {
// First identifier is shortcode name.
// myshortcode or myshortcode.html, no layout.
if len(p.identifiersKnown) <= 2 {
p.posIdentifierLayout = -1
} else {
// First is always the name.
p.posIdentifierLayout--
}
}

View file

@ -434,12 +434,12 @@ func TestParseLayouts(t *testing.T) {
},
{
"Layout multiple",
"/mylayout.list.section.no.html",
"/maylayout.list.section.no.html",
func(c *qt.C, p *Path) {
c.Assert(p.Layout(), qt.Equals, "mylayout")
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "section", "list", "mylayout"})
c.Assert(p.Layout(), qt.Equals, "maylayout")
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "no", "section", "list", "maylayout"})
c.Assert(p.IdentifiersUnknown(), qt.DeepEquals, []string{})
c.Assert(p.Base(), qt.Equals, "/mylayout.html")
c.Assert(p.Base(), qt.Equals, "/maylayout.html")
c.Assert(p.Lang(), qt.Equals, "no")
},
},
@ -487,8 +487,7 @@ func TestParseLayouts(t *testing.T) {
func(c *qt.C, p *Path) {
c.Assert(p.Base(), qt.Equals, "/_shortcodes/myshortcode.html")
c.Assert(p.Type(), qt.Equals, TypeShortcode)
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "list"})
c.Assert(p.Layout(), qt.Equals, "list")
c.Assert(p.Identifiers(), qt.DeepEquals, []string{"html", "list", "myshortcode"})
c.Assert(p.PathNoIdentifier(), qt.Equals, "/_shortcodes/myshortcode")
c.Assert(p.PathBeforeLangAndOutputFormatAndExt(), qt.Equals, "/_shortcodes/myshortcode.list")
c.Assert(p.Lang(), qt.Equals, "")
@ -564,30 +563,11 @@ func TestParseLayouts(t *testing.T) {
c.Assert(p.Type(), qt.Equals, TypePartial)
},
},
{
"Shortcode lang in root",
"/_shortcodes/no.html",
func(c *qt.C, p *Path) {
c.Assert(p.Type(), qt.Equals, TypeShortcode)
c.Assert(p.Lang(), qt.Equals, "")
c.Assert(p.NameNoIdentifier(), qt.Equals, "no")
},
},
{
"Shortcode lang layout",
"/_shortcodes/myshortcode.no.html",
func(c *qt.C, p *Path) {
c.Assert(p.Type(), qt.Equals, TypeShortcode)
c.Assert(p.Lang(), qt.Equals, "no")
c.Assert(p.Layout(), qt.Equals, "")
c.Assert(p.NameNoIdentifier(), qt.Equals, "myshortcode")
},
},
}
for _, test := range tests {
c.Run(test.name, func(c *qt.C) {
if test.name != "Shortcode lang layout" {
if test.name != "Baseof" {
// return
}
test.assert(c, testParser.Parse(files.ComponentFolderLayouts, test.path))

View file

@ -17,6 +17,7 @@ package terminal
import (
"fmt"
"os"
"runtime"
"strings"
isatty "github.com/mattn/go-isatty"
@ -40,6 +41,10 @@ func PrintANSIColors(f *os.File) bool {
// IsTerminal return true if the file descriptor is terminal and the TERM
// environment variable isn't a dumb one.
func IsTerminal(f *os.File) bool {
if runtime.GOOS == "windows" {
return false
}
fd := f.Fd()
return os.Getenv("TERM") != "dumb" && (isatty.IsTerminal(fd) || isatty.IsCygwinTerminal(fd))
}

View file

@ -146,7 +146,7 @@ type Config struct {
// The cascade configuration section contains the top level front matter cascade configuration options,
// a slice of page matcher and params to apply to those pages.
Cascade *config.ConfigNamespace[[]page.PageMatcherParamsConfig, *maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig]] `mapstructure:"-"`
Cascade *config.ConfigNamespace[[]page.PageMatcherParamsConfig, *maps.Ordered[page.PageMatcher, maps.Params]] `mapstructure:"-"`
// The segments defines segments for the site. Used for partial/segmented builds.
Segments *config.ConfigNamespace[map[string]segments.SegmentConfig, segments.Segments] `mapstructure:"-"`
@ -776,7 +776,7 @@ type Configs struct {
}
func (c *Configs) Validate(logger loggers.Logger) error {
c.Base.Cascade.Config.Range(func(p page.PageMatcher, cfg page.PageMatcherParamsConfig) bool {
c.Base.Cascade.Config.Range(func(p page.PageMatcher, params maps.Params) bool {
page.CheckCascadePattern(logger, p)
return true
})

View file

@ -36,7 +36,6 @@ import (
"github.com/dustin/go-humanize"
"github.com/gobwas/glob"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/para"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/deploy/deployconfig"
"github.com/gohugoio/hugo/media"
@ -488,12 +487,7 @@ func knownHiddenDirectory(name string) bool {
// walkLocal walks the source directory and returns a flat list of files,
// using localFile.SlashPath as the map keys.
func (d *Deployer) walkLocal(fs afero.Fs, matchers []*deployconfig.Matcher, include, exclude glob.Glob, mediaTypes media.Types, mappath func(string) string) (map[string]*localFile, error) {
retval := make(map[string]*localFile)
var mu sync.Mutex
workers := para.New(d.cfg.Workers)
g, _ := workers.Start(context.Background())
retval := map[string]*localFile{}
err := afero.Walk(fs, "", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
@ -514,54 +508,45 @@ func (d *Deployer) walkLocal(fs afero.Fs, matchers []*deployconfig.Matcher, incl
return nil
}
// Process each file in a worker
g.Run(func() error {
// When a file system is HFS+, its filepath is in NFD form.
if runtime.GOOS == "darwin" {
path = norm.NFC.String(path)
}
// When a file system is HFS+, its filepath is in NFD form.
if runtime.GOOS == "darwin" {
path = norm.NFC.String(path)
}
// Check include/exclude matchers.
slashpath := filepath.ToSlash(path)
if include != nil && !include.Match(slashpath) {
d.logger.Infof(" dropping %q due to include\n", slashpath)
return nil
}
if exclude != nil && exclude.Match(slashpath) {
d.logger.Infof(" dropping %q due to exclude\n", slashpath)
return nil
}
// Find the first matching matcher (if any).
var m *deployconfig.Matcher
for _, cur := range matchers {
if cur.Matches(slashpath) {
m = cur
break
}
}
// Apply any additional modifications to the local path, to map it to
// the remote path.
if mappath != nil {
slashpath = mappath(slashpath)
}
lf, err := newLocalFile(fs, path, slashpath, m, mediaTypes)
if err != nil {
return err
}
mu.Lock()
retval[lf.SlashPath] = lf
mu.Unlock()
// Check include/exclude matchers.
slashpath := filepath.ToSlash(path)
if include != nil && !include.Match(slashpath) {
d.logger.Infof(" dropping %q due to include\n", slashpath)
return nil
})
}
if exclude != nil && exclude.Match(slashpath) {
d.logger.Infof(" dropping %q due to exclude\n", slashpath)
return nil
}
// Find the first matching matcher (if any).
var m *deployconfig.Matcher
for _, cur := range matchers {
if cur.Matches(slashpath) {
m = cur
break
}
}
// Apply any additional modifications to the local path, to map it to
// the remote path.
if mappath != nil {
slashpath = mappath(slashpath)
}
lf, err := newLocalFile(fs, path, slashpath, m, mediaTypes)
if err != nil {
return err
}
retval[lf.SlashPath] = lf
return nil
})
if err != nil {
return nil, err
}
if err := g.Wait(); err != nil {
return nil, err
}
return retval, nil
}

View file

@ -623,7 +623,7 @@ func TestEndToEndSync(t *testing.T) {
localFs: test.fs,
bucket: test.bucket,
mediaTypes: media.DefaultTypes,
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1},
cfg: deployconfig.DeployConfig{MaxDeletes: -1},
}
// Initial deployment should sync remote with local.
@ -706,7 +706,7 @@ func TestMaxDeletes(t *testing.T) {
localFs: test.fs,
bucket: test.bucket,
mediaTypes: media.DefaultTypes,
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1},
cfg: deployconfig.DeployConfig{MaxDeletes: -1},
}
// Sync remote with local.
@ -836,7 +836,7 @@ func TestIncludeExclude(t *testing.T) {
}
deployer := &Deployer{
localFs: fsTest.fs,
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1}, bucket: fsTest.bucket,
cfg: deployconfig.DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
target: tgt,
mediaTypes: media.DefaultTypes,
}
@ -893,7 +893,7 @@ func TestIncludeExcludeRemoteDelete(t *testing.T) {
}
deployer := &Deployer{
localFs: fsTest.fs,
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1}, bucket: fsTest.bucket,
cfg: deployconfig.DeployConfig{MaxDeletes: -1}, bucket: fsTest.bucket,
mediaTypes: media.DefaultTypes,
}
@ -945,7 +945,7 @@ func TestCompression(t *testing.T) {
deployer := &Deployer{
localFs: test.fs,
bucket: test.bucket,
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: ".*", Gzip: true, Re: regexp.MustCompile(".*")}}},
cfg: deployconfig.DeployConfig{MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: ".*", Gzip: true, Re: regexp.MustCompile(".*")}}},
mediaTypes: media.DefaultTypes,
}
@ -1000,7 +1000,7 @@ func TestMatching(t *testing.T) {
deployer := &Deployer{
localFs: test.fs,
bucket: test.bucket,
cfg: deployconfig.DeployConfig{Workers: 2, MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: "^subdir/aaa$", Force: true, Re: regexp.MustCompile("^subdir/aaa$")}}},
cfg: deployconfig.DeployConfig{MaxDeletes: -1, Matchers: []*deployconfig.Matcher{{Pattern: "^subdir/aaa$", Force: true, Re: regexp.MustCompile("^subdir/aaa$")}}},
mediaTypes: media.DefaultTypes,
}
@ -1097,6 +1097,5 @@ func verifyRemote(ctx context.Context, bucket *blob.Bucket, local []*fileData) (
func newDeployer() *Deployer {
return &Deployer{
logger: loggers.NewDefault(),
cfg: deployconfig.DeployConfig{Workers: 2},
}
}

96
go.mod
View file

@ -2,9 +2,9 @@ module github.com/gohugoio/hugo
require (
github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69
github.com/alecthomas/chroma/v2 v2.18.0
github.com/alecthomas/chroma/v2 v2.17.2
github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c
github.com/aws/aws-sdk-go-v2 v1.36.4
github.com/aws/aws-sdk-go-v2 v1.36.1
github.com/aws/aws-sdk-go-v2/service/cloudfront v1.44.10
github.com/bep/clocks v0.5.0
github.com/bep/debounce v1.2.0
@ -26,7 +26,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.5
github.com/evanw/esbuild v0.25.3
github.com/fatih/color v1.18.0
github.com/fortytw2/leaktest v1.3.0
github.com/frankban/quicktest v1.14.6
@ -54,46 +54,44 @@ require (
github.com/mattn/go-isatty v0.0.20
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c
github.com/muesli/smartcrop v0.3.0
github.com/niklasfasching/go-org v1.8.0
github.com/olekukonko/tablewriter v1.0.7
github.com/niklasfasching/go-org v1.7.0
github.com/olekukonko/tablewriter v0.0.5
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/cast v1.7.1
github.com/spf13/cobra v1.9.1
github.com/spf13/fsync v0.10.1
github.com/spf13/pflag v1.0.6
github.com/tdewolff/minify/v2 v2.23.8
github.com/tdewolff/parse/v2 v2.8.1
github.com/tdewolff/minify/v2 v2.20.37
github.com/tdewolff/parse/v2 v2.7.15
github.com/tetratelabs/wazero v1.9.0
github.com/yuin/goldmark v1.7.12
github.com/yuin/goldmark v1.7.11
github.com/yuin/goldmark-emoji v1.0.6
go.uber.org/automaxprocs v1.5.3
gocloud.dev v0.40.0
golang.org/x/exp v0.0.0-20221031165847-c99f073a8326
golang.org/x/image v0.28.0
golang.org/x/mod v0.25.0
golang.org/x/net v0.41.0
golang.org/x/sync v0.15.0
golang.org/x/text v0.26.0
golang.org/x/tools v0.33.0
google.golang.org/api v0.237.0
golang.org/x/image v0.26.0
golang.org/x/mod v0.24.0
golang.org/x/net v0.39.0
golang.org/x/sync v0.13.0
golang.org/x/text v0.24.0
golang.org/x/tools v0.32.0
google.golang.org/api v0.221.0
gopkg.in/yaml.v2 v2.4.0
rsc.io/qr v0.2.0
)
require (
cel.dev/expr v0.23.0 // indirect
cloud.google.com/go v0.120.0 // indirect
cloud.google.com/go/auth v0.16.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.7.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.50.0 // indirect
cloud.google.com/go v0.116.0 // indirect
cloud.google.com/go/auth v0.14.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.2.2 // indirect
cloud.google.com/go/storage v1.43.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
@ -101,9 +99,6 @@ require (
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0 // indirect
github.com/aws/aws-sdk-go v1.55.5 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
github.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect
@ -123,13 +118,9 @@ require (
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
github.com/aws/smithy-go v1.22.2 // indirect
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
github.com/dlclark/regexp2 v1.11.5 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
@ -139,8 +130,8 @@ require (
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/google/wire v0.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.14.2 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
@ -150,40 +141,31 @@ require (
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect
github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 // indirect
github.com/olekukonko/ll v0.0.8 // indirect
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/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
github.com/zeebo/errs v1.4.0 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.35.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
go.opentelemetry.io/otel v1.36.0 // indirect
go.opentelemetry.io/otel/metric v1.36.0 // indirect
go.opentelemetry.io/otel/sdk v1.36.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect
golang.org/x/crypto v0.39.0 // indirect
golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/time v0.12.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/oauth2 v0.26.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/time v0.10.0 // indirect
golang.org/x/xerrors v0.0.0-20240716161551-93cc26a95ae9 // indirect
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect
google.golang.org/grpc v1.73.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.5 // 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

217
go.sum
View file

@ -1,5 +1,3 @@
cel.dev/expr v0.23.0 h1:wUb94w6OYQS4uXraxo9U+wUAs9jT47Xvl4iPgAwM2ss=
cel.dev/expr v0.23.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@ -19,30 +17,26 @@ cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHOb
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
cloud.google.com/go v0.120.0 h1:wc6bgG9DHyKqF5/vQvX1CiZrtHnxJjBlKUyF9nP6meA=
cloud.google.com/go v0.120.0/go.mod h1:/beW32s8/pGRuj4IILWQNd4uuebeT4dkOhKmkfit64Q=
cloud.google.com/go/auth v0.16.2 h1:QvBAGFPLrDeoiNjyfVunhQ10HKNYuOwZ5noee0M5df4=
cloud.google.com/go/auth v0.16.2/go.mod h1:sRBas2Y1fB1vZTdurouM0AzuYQBMZinrUYL8EufhtEA=
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
cloud.google.com/go/auth v0.14.1 h1:AwoJbzUdxA/whv1qj3TLKwh3XX5sikny2fc40wUl+h0=
cloud.google.com/go/auth v0.14.1/go.mod h1:4JHUxlGXisL0AW8kXPtUF6ztuOksyfUQNFjfsOCXkPM=
cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M=
cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
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.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU=
cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
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=
cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE=
cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc=
cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA=
cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
cloud.google.com/go/monitoring v1.24.2 h1:5OTsoJ1dXYIiMiuL+sYscLc9BumrL3CarVLL7dd7lHM=
cloud.google.com/go/monitoring v1.24.2/go.mod h1:x7yzPWcgDRnPEv3sI+jJGBkwl5qINf+6qY4eq0I9B4U=
cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA=
cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY=
cloud.google.com/go/longrunning v0.6.2 h1:xjDfh1pQcWPEvnfjZmwjKQEcHnpz6lHjfy7Fo0MK+hc=
cloud.google.com/go/longrunning v0.6.2/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@ -53,10 +47,8 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
cloud.google.com/go/storage v1.50.0 h1:3TbVkzTooBvnZsk7WaAQfOsNrdoM8QHusXA1cpk6QJs=
cloud.google.com/go/storage v1.50.0/go.mod h1:l7XeiD//vx5lfqE3RavfmU9yvk5Pp0Zhcv482poyafY=
cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4=
cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI=
cloud.google.com/go/storage v1.43.0 h1:CcxnSohZwizt4LCzQHWvBf1/kvtHUn7gk9QERXPyXFs=
cloud.google.com/go/storage v1.43.0/go.mod h1:ajvxEa7WmZS1PxvKRq4bq0tFT3vMd502JwstCcYv0Q0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0=
@ -79,26 +71,18 @@ github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69/go.mod h1:L1AbZd
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0 h1:5IT7xOdq17MtcdtL/vtl6mGfzhaq4m4vpollPRmlsBQ=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50.0/go.mod h1:ZV4VOm0/eHR06JLrXWe09068dHpr3TRpY9Uo7T+anuA=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.50.0 h1:nNMpRpnkWDAaqcpxMJvxa/Ud98gjbYwayJY4/9bdjiU=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.50.0/go.mod h1:SZiPHWGOOk3bl8tkevxkoiwPgsIl6CwrWcbwjfHZpdM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0 h1:ig/FpDD2JofP/NExKQUbn7uOSZzJAQqogfqluZK4ed4=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0=
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.18.0 h1:6h53Q4hW83SuF+jcsp7CVhLsMozzvQvO8HBbKQW+gn4=
github.com/alecthomas/chroma/v2 v2.18.0/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI=
github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c h1:651/eoCRnQ7YtSjAnSzRucrJz+3iGEFt+ysraELS81M=
github.com/armon/go-radix v1.0.1-0.20221118154546-54df44f2176c/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go-v2 v1.36.4 h1:GySzjhVvx0ERP6eyfAbAuAXLtAda5TEy19E5q5W8I9E=
github.com/aws/aws-sdk-go-v2 v1.36.4/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
github.com/aws/aws-sdk-go-v2 v1.36.1 h1:iTDl5U6oAhkNPba0e1t1hrwAo02ZMqbrGq4k5JBWM5E=
github.com/aws/aws-sdk-go-v2 v1.36.1/go.mod h1:5PMILGVKiW32oDzjj6RU52yrNrDPUHcbZQYr1sM7qmM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 h1:tW1/Rkad38LA15X4UQtjXZXNKsCgkshC3EbmcUmghTg=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3/go.mod h1:UbnqO+zjqk3uIt9yCACHJ9IVNhyhOCnYk8yA19SAWrM=
github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=
@ -183,8 +167,6 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f h1:C5bqEmzEPLsHm9Mv73lSE9e9bKV23aB1vxOsmZrkl3k=
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
@ -203,17 +185,9 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA=
github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A=
github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
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.5 h1:E+JpeY5S/1LFmnX1vtuZqUKT7qDVcfXdhzMhM3uIKFs=
github.com/evanw/esbuild v0.25.5/go.mod h1:D2vIQZqV/vIf/VRHtViaUtViZmG7o+kKmlBfVQuRi48=
github.com/evanw/esbuild v0.25.3 h1:4JKyUsm/nHDhpxis4IyWXAi8GiyTwG1WdEp6OhGVE8U=
github.com/evanw/esbuild v0.25.3/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=
@ -234,8 +208,6 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@ -345,12 +317,12 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI=
github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA=
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.14.2 h1:eBLnkZ9635krYIPD+ag1USrOAI0Nr0QYF3+/3GqO0k0=
github.com/googleapis/gax-go/v2 v2.14.2/go.mod h1:ON64QhlJkhVtSqp4v1uaK92VyZ2gmvDQsweuyLV+8+w=
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@ -404,8 +376,8 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE=
github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
@ -416,18 +388,14 @@ github.com/muesli/smartcrop v0.3.0/go.mod h1:i2fCI/UorTfgEpPPLWiFBv4pye+YAG78Rwc
github.com/neurosnap/sentences v1.0.6/go.mod h1:pg1IapvYpWCJJm/Etxeh0+gtMf1rI1STY9S7eUCPbDc=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/niklasfasching/go-org v1.8.0 h1:WyGLaajLLp8JbQzkmapZ1y0MOzKuKV47HkZRloi+HGY=
github.com/niklasfasching/go-org v1.8.0/go.mod h1:e2A9zJs7cdONrEGs3gvxCcaAEpwwPNPG7csDpXckMNg=
github.com/niklasfasching/go-org v1.7.0 h1:vyMdcMWWTe/XmANk19F4k8XGBYg0GQ/gJGMimOjGMek=
github.com/niklasfasching/go-org v1.7.0/go.mod h1:WuVm4d45oePiE0eX25GqTDQIt/qPW1T9DGkRscqLW5o=
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY=
github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw=
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c=
github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6 h1:r3FaAI0NZK3hSmtTDrBVREhKULp8oUeqLT5Eyl2mSPo=
github.com/olekukonko/errors v0.0.0-20250405072817-4e6d85265da6/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
github.com/olekukonko/ll v0.0.8 h1:sbGZ1Fx4QxJXEqL/6IG8GEFnYojUSQ45dJVwN2FH2fc=
github.com/olekukonko/ll v0.0.8/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
github.com/olekukonko/tablewriter v1.0.7 h1:HCC2e3MM+2g72M81ZcJU11uciw6z/p82aEnm4/ySDGw=
github.com/olekukonko/tablewriter v1.0.7/go.mod h1:H428M+HzoUXC6JU2Abj9IT9ooRmdq9CxuDmKMtrOCMs=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
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=
@ -440,16 +408,12 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
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=
@ -464,16 +428,14 @@ github.com/shogo82148/go-shuffle v0.0.0-20180218125048-27e6095f230d/go.mod h1:2h
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/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
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=
github.com/spf13/fsync v0.10.1/go.mod h1:y+B41vYq5i6Boa3Z+BVoPbDeOvxVkNU5OBXhoT8i4TQ=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE=
github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@ -487,12 +449,13 @@ 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.23.8 h1:tvjHzRer46kwOfpdCBCWsDblCw3QtnLJRd61pTVkyZ8=
github.com/tdewolff/minify/v2 v2.23.8/go.mod h1:VW3ISUd3gDOZuQ/jwZr4sCzsuX+Qvsx87FDMjk6Rvno=
github.com/tdewolff/parse/v2 v2.8.1 h1:J5GSHru6o3jF1uLlEKVXkDxxcVx6yzOlIVIotK4w2po=
github.com/tdewolff/parse/v2 v2.8.1/go.mod h1:Hwlni2tiVNKyzR1o6nUs4FOF07URA+JLBLd6dlIXYqo=
github.com/tdewolff/test v1.0.11 h1:FdLbwQVHxqG16SlkGveC0JVyrJN62COWTRyUFzfbtBE=
github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
github.com/tdewolff/minify/v2 v2.20.37 h1:Q97cx4STXCh1dlWDlNHZniE8BJ2EBL0+2b0n92BJQhw=
github.com/tdewolff/minify/v2 v2.20.37/go.mod h1:L1VYef/jwKw6Wwyk5A+T0mBjjn3mMPgmjjA688RNsxU=
github.com/tdewolff/parse/v2 v2.7.15 h1:hysDXtdGZIRF5UZXwpfn3ZWRbm+ru4l53/ajBRGpCTw=
github.com/tdewolff/parse/v2 v2.7.15/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
github.com/tetratelabs/wazero v1.9.0 h1:IcZ56OuxrtaEz8UYNRHBrUa9bYeX9oVY93KspZZBf/I=
github.com/tetratelabs/wazero v1.9.0/go.mod h1:TSbcXCfFP0L2FGkRPxHphadXPjo1T6W+CseNNY7EkjM=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
@ -503,12 +466,10 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.12 h1:YwGP/rrea2/CnCtUHgjuolG/PnMxdQtPMO5PvaE2/nY=
github.com/yuin/goldmark v1.7.12/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/yuin/goldmark v1.7.11 h1:ZCxLyDMtz0nT2HFfsYG8WZ47Trip2+JyLysKcMYE5bo=
github.com/yuin/goldmark v1.7.11/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs=
github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA=
github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM=
github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@ -519,24 +480,20 @@ go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/detectors/gcp v1.35.0 h1:bGvFt68+KTiAKFlacHW6AhA56GF2rS0bdD3aJYEnmzA=
go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0 h1:q4XOmH/0opmeuJtPsbFNivyl7bCt7yRBbeEm2sC/XtQ=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.61.0/go.mod h1:snMWehoOh2wsEwnvvwtDyFCxVeDAODenXHtn5vzrKjo=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc=
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I=
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
gocloud.dev v0.40.0 h1:f8LgP+4WDqOG/RXoUcyLpeIAGOcAbZrZbDQCUee10ng=
@ -552,8 +509,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.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
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=
@ -569,8 +526,8 @@ golang.org/x/exp v0.0.0-20221031165847-c99f073a8326/go.mod h1:CxIveKay+FTh1D0yPZ
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.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE=
golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY=
golang.org/x/image v0.26.0 h1:4XjIFEZWQmCZi6Wv8BoxsDhRU3RVnLX04dToTDAEPlY=
golang.org/x/image v0.26.0/go.mod h1:lcxbMFAovzpnJxzXS3nyL83K27tmqtKzIJpctK8YO5c=
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=
@ -597,8 +554,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.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
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=
@ -638,8 +595,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.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw=
golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA=
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
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=
@ -649,8 +606,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.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
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=
@ -666,8 +623,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.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8=
golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
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=
@ -715,8 +672,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.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
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=
@ -735,13 +692,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.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M=
golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA=
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
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.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
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=
@ -794,8 +751,8 @@ 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.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc=
golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI=
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
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=
@ -821,8 +778,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.237.0 h1:MP7XVsGZesOsx3Q8WVa4sUdbrsTvDSOERd3Vh4xj/wc=
google.golang.org/api v0.237.0/go.mod h1:cOVEm2TpdAGHL2z+UwyS+kmlGr3bVWQQ6sYEqkKje50=
google.golang.org/api v0.221.0 h1:qzaJfLhDsbMeFee8zBRdt/Nc+xmOuafD/dbdgGfutOU=
google.golang.org/api v0.221.0/go.mod h1:7sOU2+TL4TxUTdbi0gWgAIg7tH5qBXxoyhtL+9x3biQ=
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=
@ -866,12 +823,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2 h1:1tXaIXCracvtsRxSBsYDiSBN0cuJvM7QYW+MrpIRY78=
google.golang.org/genproto v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:49MsLSx0oWMOZqcpB3uL8ZOkAh1+TndpJ8ONoCBWiZk=
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2 h1:vPV0tzlsK6EzEDHNNH5sa7Hs9bd7iXR7B1tSiPepkV0=
google.golang.org/genproto/googleapis/api v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:pKLAc5OolXC3ViWGI62vvC0n10CpwAtRcTNCFwTKBEw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 h1:fc6jSaCT0vBduLYZHYrBBNY4dsWuvgyff9noRNDdBeE=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28 h1:KJjNNclfpIkVqrZlTWcgOOaVQ00LdBnoEaRfkUx760s=
google.golang.org/genproto v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:mt9/MofW7AWQ+Gy179ChOnvmJatV8YHUmrcedo9CIFI=
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 h1:CkkIfIt50+lT6NHAVoRYEyAvQGFM7xEwXUUywFvEb3Q=
google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576/go.mod h1:1R3kvZ1dtP3+4p4d3G8uJ8rFk/fWlScl38vanWACI08=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 h1:2duwAxN2+k0xLNpjnHTXoMUgnv6VPSp5fiqTuwSxjmI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
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=
@ -888,8 +845,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.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
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=
@ -900,8 +857,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.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
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=

View file

@ -19,8 +19,6 @@ import (
"sync/atomic"
"github.com/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
"github.com/olekukonko/tablewriter/tw"
)
// ProcessingStats represents statistics about a site build.
@ -68,6 +66,23 @@ func (s *ProcessingStats) Add(counter *uint64, amount int) {
atomic.AddUint64(counter, uint64(amount))
}
// Table writes a table-formatted representation of the stats in a
// ProcessingStats instance to w.
func (s *ProcessingStats) Table(w io.Writer) {
titleVals := s.toVals()
data := make([][]string, len(titleVals))
for i, tv := range titleVals {
data[i] = []string{tv.name, strconv.Itoa(int(tv.val))}
}
table := tablewriter.NewWriter(w)
table.AppendBulk(data)
table.SetHeader([]string{"", s.Name})
table.SetBorder(false)
table.Render()
}
// ProcessingStatsTable writes a table-formatted representation of stats to w.
func ProcessingStatsTable(w io.Writer, stats ...*ProcessingStats) {
names := make([]string, len(stats)+1)
@ -91,26 +106,13 @@ func ProcessingStatsTable(w io.Writer, stats ...*ProcessingStats) {
data[j] = append(data[j], strconv.Itoa(int(tv.val)))
}
}
}
table := tablewriter.NewTable(
w,
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
Borders: tw.BorderNone,
Symbols: tw.NewSymbols(tw.StyleLight),
Settings: tw.Settings{
Separators: tw.Separators{BetweenRows: tw.Off},
Lines: tw.Lines{ShowFooterLine: tw.On},
},
})),
tablewriter.WithConfig(
tablewriter.Config{
MaxWidth: 70,
Row: tw.CellConfig{Alignment: tw.CellAlignment{Global: tw.AlignRight, PerColumn: []tw.Align{tw.AlignLeft}}},
}),
)
table := tablewriter.NewWriter(w)
table.Bulk(data)
table.Header(names)
table.AppendBulk(data)
table.SetHeader(names)
table.SetBorder(false)
table.Render()
}

View file

@ -892,7 +892,7 @@ disableKinds = ['home','rss','sitemap','taxonomy','term']
---
title: s
cascade:
build:
_build:
render: never
---
-- content/s/p1.md --
@ -917,51 +917,3 @@ title: p2
b.AssertFileExists("public/sx/index.html", true) // failing
b.AssertFileExists("public/sx/p2/index.html", true) // failing
}
func TestCascadeGotmplIssue13743(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['home','rss','section','sitemap','taxonomy','term']
[cascade.params]
foo = 'bar'
[cascade.target]
path = '/p1'
-- content/_content.gotmpl --
{{ .AddPage (dict "title" "p1" "path" "p1") }}
-- layouts/all.html --
{{ .Title }}|{{ .Params.foo }}
`
b := Test(t, files)
b.AssertFileContent("public/p1/index.html", "p1|bar") // actual content is "p1|"
}
func TestCascadeWarnOverrideIssue13806(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['home','rss','section','sitemap','taxonomy','term']
[[cascade]]
[cascade.params]
searchable = true
[cascade.target]
kind = 'page'
-- content/something.md --
---
title: Something
params:
searchable: false
---
-- layouts/all.html --
All.
`
b := Test(t, files, TestOptWarn())
b.AssertLogContains("! WARN")
}

View file

@ -1406,7 +1406,7 @@ home = ["html"]
"home": {"html"},
"page": {"html"},
"rss": {"rss"},
"section": {},
"section": nil,
"taxonomy": {"html", "rss"},
"term": {"html", "rss"},
})

View file

@ -21,6 +21,7 @@ import (
"sort"
"strconv"
"strings"
"sync"
"sync/atomic"
"time"
@ -1309,6 +1310,7 @@ func (h *HugoSites) resolveAndResetDependententPageOutputs(ctx context.Context,
}
po.renderState = 0
po.p.resourcesPublishInit = &sync.Once{}
if r == identity.FinderFoundOneOfMany || po.f.Name == output.HTTPStatus404HTMLFormat.Name {
// Will force a re-render even in fast render mode.
po.renderOnce = false
@ -1410,7 +1412,7 @@ func (sa *sitePagesAssembler) applyAggregates() error {
}
// Handle cascades first to get any default dates set.
var cascade *maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig]
var cascade *maps.Ordered[page.PageMatcher, maps.Params]
if keyPage == "" {
// Home page gets it's cascade from the site config.
cascade = sa.conf.Cascade.Config
@ -1422,7 +1424,7 @@ func (sa *sitePagesAssembler) applyAggregates() error {
} else {
_, data := pw.WalkContext.Data().LongestPrefix(paths.Dir(keyPage))
if data != nil {
cascade = data.(*maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig])
cascade = data.(*maps.Ordered[page.PageMatcher, maps.Params])
}
}
@ -1504,11 +1506,11 @@ func (sa *sitePagesAssembler) applyAggregates() error {
pageResource := rs.r.(*pageState)
relPath := pageResource.m.pathInfo.BaseRel(pageBundle.m.pathInfo)
pageResource.m.resourcePath = relPath
var cascade *maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig]
var cascade *maps.Ordered[page.PageMatcher, maps.Params]
// Apply cascade (if set) to the page.
_, data := pw.WalkContext.Data().LongestPrefix(resourceKey)
if data != nil {
cascade = data.(*maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig])
cascade = data.(*maps.Ordered[page.PageMatcher, maps.Params])
}
if err := pageResource.setMetaPost(cascade); err != nil {
return false, err
@ -1572,10 +1574,10 @@ func (sa *sitePagesAssembler) applyAggregatesToTaxonomiesAndTerms() error {
const eventName = "dates"
if p.Kind() == kinds.KindTerm {
var cascade *maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig]
var cascade *maps.Ordered[page.PageMatcher, maps.Params]
_, data := pw.WalkContext.Data().LongestPrefix(s)
if data != nil {
cascade = data.(*maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig])
cascade = data.(*maps.Ordered[page.PageMatcher, maps.Params])
}
if err := p.setMetaPost(cascade); err != nil {
return false, err

View file

@ -44,14 +44,14 @@ tags: ["mytag"]
`, "sect/no-list.md", `
---
title: No List
build:
_build:
list: false
---
`, "sect/no-render.md", `
---
title: No List
build:
_build:
render: false
---
`,
@ -59,14 +59,14 @@ build:
---
title: No Render Link
aliases: ["/link-alias"]
build:
_build:
render: link
---
`,
"sect/no-publishresources/index.md", `
---
title: No Publish Resources
build:
_build:
publishResources: false
---
@ -81,7 +81,7 @@ headless: true
---
title: Headless Local Lists
cascade:
build:
_build:
render: false
list: local
publishResources: false
@ -365,7 +365,7 @@ Data1: {{ $data1.RelPermalink }}
`)
b.WithContent("section/bundle-false/index.md", `---\ntitle: BundleFalse
build:
_build:
publishResources: false
---`,
"section/bundle-false/data1.json", "Some data1",
@ -388,7 +388,7 @@ func TestNoRenderAndNoPublishResources(t *testing.T) {
noRenderPage := `
---
title: %s
build:
_build:
render: false
publishResources: false
---

View file

@ -263,7 +263,7 @@ func (s *IntegrationTestBuilder) AssertLogContains(els ...string) {
}
}
// AssertLogMatches asserts that the last build log matches the given regular expressions.
// AssertLogNotContains asserts that the last build log does matches the given regular expressions.
// The regular expressions can be negated with a "! " prefix.
func (s *IntegrationTestBuilder) AssertLogMatches(expression string) {
s.Helper()

View file

@ -19,6 +19,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
"sync/atomic"
"github.com/gohugoio/hugo/hugofs"
@ -28,7 +29,6 @@ import (
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/output"
"github.com/gohugoio/hugo/related"
"github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/tpl/tplimpl"
"github.com/spf13/afero"
@ -110,7 +110,8 @@ type pageState struct {
*pageCommon
resource.Staler
dependencyManager identity.Manager
dependencyManager identity.Manager
resourcesPublishInit *sync.Once
}
func (p *pageState) incrPageOutputTemplateVariation() {
@ -521,35 +522,39 @@ func (p *pageState) initPage() error {
}
func (p *pageState) renderResources() error {
for _, r := range p.Resources() {
var initErr error
if _, ok := r.(page.Page); ok {
if p.s.h.buildCounter.Load() == 0 {
p.resourcesPublishInit.Do(func() {
for _, r := range p.Resources() {
if _, ok := r.(page.Page); ok {
// Pages gets rendered with the owning page but we count them here.
p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Pages)
continue
}
continue
}
if resources.IsPublished(r) {
continue
}
src, ok := r.(resource.Source)
if !ok {
return fmt.Errorf("resource %T does not support resource.Source", r)
}
if err := src.Publish(); err != nil {
if !herrors.IsNotExist(err) {
p.s.Log.Errorf("Failed to publish Resource for page %q: %s", p.pathOrTitle(), err)
if _, isWrapper := r.(resource.ResourceWrapper); isWrapper {
// Skip resources that are wrapped.
// These gets published on its own.
continue
}
} else {
p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Files)
}
}
return nil
src, ok := r.(resource.Source)
if !ok {
initErr = fmt.Errorf("resource %T does not support resource.Source", r)
return
}
if err := src.Publish(); err != nil {
if !herrors.IsNotExist(err) {
p.s.Log.Errorf("Failed to publish Resource for page %q: %s", p.pathOrTitle(), err)
}
} else {
p.s.PathSpec.ProcessingStats.Incr(&p.s.PathSpec.ProcessingStats.Files)
}
}
})
return initErr
}
func (p *pageState) AlternativeOutputFormats() page.OutputFormats {

View file

@ -29,6 +29,7 @@ import (
"github.com/gohugoio/hugo/source"
"github.com/gohugoio/hugo/common/constants"
"github.com/gohugoio/hugo/common/hashing"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/loggers"
@ -82,8 +83,8 @@ type pageMetaParams struct {
// These are only set in watch mode.
datesOriginal pagemeta.Dates
paramsOriginal map[string]any // contains the original params as defined in the front matter.
cascadeOriginal *maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig] // contains the original cascade as defined in the front matter.
paramsOriginal map[string]any // contains the original params as defined in the front matter.
cascadeOriginal *maps.Ordered[page.PageMatcher, maps.Params] // contains the original cascade as defined in the front matter.
}
func (m *pageMetaParams) init(preserveOriginal bool) {
@ -290,7 +291,7 @@ func (p *pageMeta) setMetaPre(pi *contentParseInfo, logger loggers.Logger, conf
return nil
}
func (ps *pageState) setMetaPost(cascade *maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig]) error {
func (ps *pageState) setMetaPost(cascade *maps.Ordered[page.PageMatcher, maps.Params]) error {
ps.m.setMetaPostCount++
var cascadeHashPre uint64
if ps.m.setMetaPostCount > 1 {
@ -302,20 +303,15 @@ func (ps *pageState) setMetaPost(cascade *maps.Ordered[page.PageMatcher, page.Pa
// Apply cascades first so they can be overridden later.
if cascade != nil {
if ps.m.pageConfig.CascadeCompiled != nil {
cascade.Range(func(k page.PageMatcher, v page.PageMatcherParamsConfig) bool {
cascade.Range(func(k page.PageMatcher, v maps.Params) bool {
vv, found := ps.m.pageConfig.CascadeCompiled.Get(k)
if !found {
ps.m.pageConfig.CascadeCompiled.Set(k, v)
} else {
// Merge
for ck, cv := range v.Params {
if _, found := vv.Params[ck]; !found {
vv.Params[ck] = cv
}
}
for ck, cv := range v.Fields {
if _, found := vv.Fields[ck]; !found {
vv.Fields[ck] = cv
for ck, cv := range v {
if _, found := vv[ck]; !found {
vv[ck] = cv
}
}
}
@ -345,17 +341,11 @@ func (ps *pageState) setMetaPost(cascade *maps.Ordered[page.PageMatcher, page.Pa
// Cascade is also applied to itself.
var err error
cascade.Range(func(k page.PageMatcher, v page.PageMatcherParamsConfig) bool {
cascade.Range(func(k page.PageMatcher, v maps.Params) bool {
if !k.Matches(ps) {
return true
}
for kk, vv := range v.Params {
if _, found := ps.m.pageConfig.Params[kk]; !found {
ps.m.pageConfig.Params[kk] = vv
}
}
for kk, vv := range v.Fields {
for kk, vv := range v {
if ps.m.pageConfig.IsFromContentAdapter {
if _, found := ps.m.pageConfig.ContentAdapterData[kk]; !found {
ps.m.pageConfig.ContentAdapterData[kk] = vv
@ -646,6 +636,9 @@ params:
}
for k, v := range userParams {
if _, found := params[k]; found {
p.s.Log.Warnidf(constants.WarnFrontMatterParamsOverrides, "Hugo front matter key %q is overridden in params section.", k)
}
params[strings.ToLower(k)] = v
}

View file

@ -16,12 +16,12 @@ package hugolib
import (
"fmt"
"strings"
"sync"
"sync/atomic"
"github.com/gohugoio/hugo/hugofs/files"
"github.com/gohugoio/hugo/resources"
"github.com/gohugoio/hugo/common/constants"
"github.com/gohugoio/hugo/common/maps"
"github.com/gohugoio/hugo/common/paths"
@ -40,14 +40,6 @@ func (h *HugoSites) newPage(m *pageMeta) (*pageState, *paths.Path, error) {
// Make sure that any partially created page part is marked as stale.
m.MarkStale()
}
if p != nil && pth != nil && p.IsHome() && pth.IsLeafBundle() {
msg := "Using %s in your content's root directory is usually incorrect for your home page. "
msg += "You should use %s instead. If you don't rename this file, your home page will be "
msg += "treated as a leaf bundle, meaning it won't be able to have any child pages or sections."
h.Log.Warnidf(constants.WarnHomePageIsLeafBundle, msg, pth.PathNoLeadingSlash(), strings.ReplaceAll(pth.PathNoLeadingSlash(), "index", "_index"))
}
return p, pth, err
}
@ -198,6 +190,7 @@ func (h *HugoSites) doNewPage(m *pageMeta) (*pageState, *paths.Path, error) {
pid: pid,
pageOutput: nopPageOutput,
pageOutputTemplateVariationsState: &atomic.Uint32{},
resourcesPublishInit: &sync.Once{},
Staler: m,
dependencyManager: m.s.Conf.NewIdentityManager(m.Path()),
pageCommon: &pageCommon{

View file

@ -1968,35 +1968,3 @@ Title: {{ .Title }}
"deprecated: path in front matter was deprecated",
)
}
// Issue 13538
func TestHomePageIsLeafBundle(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
defaultContentLanguage = 'de'
defaultContentLanguageInSubdir = true
[languages.de]
weight = 1
[languages.en]
weight = 2
-- layouts/all.html --
{{ .Title }}
-- content/index.de.md --
---
title: home de
---
-- content/index.en.org --
---
title: home en
---
`
b := Test(t, files, TestOptWarn())
b.AssertFileContent("public/de/index.html", "home de")
b.AssertFileContent("public/en/index.html", "home en")
b.AssertLogContains("Using index.de.md in your content's root directory is usually incorrect for your home page. You should use _index.de.md instead.")
b.AssertLogContains("Using index.en.org in your content's root directory is usually incorrect for your home page. You should use _index.en.org instead.")
}

View file

@ -57,7 +57,7 @@ Summary: {{ .Summary }}|
)
}
func TestFrontMatterParamsPath(t *testing.T) {
func TestFrontMatterParamsKindPath(t *testing.T) {
t.Parallel()
files := `
@ -72,9 +72,10 @@ date: 2019-08-07
path: "/a/b/c"
slug: "s1"
---
-- content/mysection/_index.md --
-- content/mysection.md --
---
title: "My Section"
kind: "section"
date: 2022-08-07
path: "/a/b"
---
@ -94,6 +95,66 @@ a/b pages: {{ range $ab.RegularPages }}{{ .Path }}|{{ .RelPermalink }}|{{ end }}
)
}
func TestFrontMatterParamsLang(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
baseURL = "https://example.org/"
disableKinds = ["taxonomy", "term"]
defaultContentLanguage = "en"
defaultContentLanguageInSubdir = true
[languages]
[languages.en]
weight = 1
[languages.nn]
weight = 2
-- content/p1.md --
---
title: "P1 nn"
lang: "nn"
---
-- content/p2.md --
---
title: "P2"
---
-- layouts/index.html --
RegularPages: {{ range site.RegularPages }}{{ .Path }}|{{ .RelPermalink }}|{{ .Title }}|{{ end }}$
`
b := Test(t, files)
b.AssertFileContent("public/en/index.html",
"RegularPages: /p2|/en/p2/|P2|$",
)
b.AssertFileContent("public/nn/index.html",
"RegularPages: /p1|/nn/p1/|P1 nn|$",
)
}
func TestFrontMatterTitleOverrideWarn(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
baseURL = "https://example.org/"
disableKinds = ["taxonomy", "term"]
-- content/p1.md --
---
title: "My title"
params:
title: "My title from params"
---
`
b := Test(t, files, TestOptWarn())
b.AssertLogContains("ARN Hugo front matter key \"title\" is overridden in params section", "You can suppress this warning")
}
func TestFrontMatterParamsLangNoCascade(t *testing.T) {
t.Parallel()

View file

@ -1766,60 +1766,6 @@ MyTemplate: {{ partial "MyTemplate.html" . }}|
b.AssertFileContent("public/index.html", "MyTemplate: MyTemplate Edited")
}
func TestRebuildEditInlinePartial13723(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
baseURL = "https://example.com"
disableLiveReload = true
title = "Foo"
-- layouts/baseof.html --
{{ block "main" . }}Main.{{ end }}
{{ partial "myinlinepartialinbaseof.html" . }}|
{{- define "_partials/myinlinepartialinbaseof.html" }}
My inline partial in baseof.
{{ end }}
-- layouts/_partials/mypartial.html --
Mypartial.
{{ partial "myinlinepartial.html" . }}|
{{- define "_partials/myinlinepartial.html" }}
Mypartial Inline.|{{ .Title }}|
{{ end }}
-- layouts/_partials/myotherpartial.html --
Myotherpartial.
{{ partial "myotherinlinepartial.html" . }}|
{{- define "_partials/myotherinlinepartial.html" }}
Myotherpartial Inline.|{{ .Title }}|
{{ return "myotherinlinepartial" }}
{{ end }}
-- layouts/all.html --
{{ define "main" }}
{{ partial "mypartial.html" . }}|
{{ partial "myotherpartial.html" . }}|
{{ partial "myinlinepartialinall.html" . }}|
{{ end }}
{{- define "_partials/myinlinepartialinall.html" }}
My inline partial in all.
{{ end }}
`
b := TestRunning(t, files)
b.AssertFileContent("public/index.html", "Mypartial.", "Mypartial Inline.|Foo")
// Edit inline partial in partial.
b.EditFileReplaceAll("layouts/_partials/mypartial.html", "Mypartial Inline.", "Mypartial Inline Edited.").Build()
b.AssertFileContent("public/index.html", "Mypartial Inline Edited.|Foo")
// Edit inline partial in baseof.
b.EditFileReplaceAll("layouts/baseof.html", "My inline partial in baseof.", "My inline partial in baseof Edited.").Build()
b.AssertFileContent("public/index.html", "My inline partial in baseof Edited.")
// Edit inline partial in all.
b.EditFileReplaceAll("layouts/all.html", "My inline partial in all.", "My inline partial in all Edited.").Build()
b.AssertFileContent("public/index.html", "My inline partial in all Edited.")
}
func TestRebuildEditAsciidocContentFile(t *testing.T) {
if !asciidocext.Supports() {
t.Skip("skip asciidoc")
@ -1946,23 +1892,3 @@ tags: ["tag1"]
// But that is a harder problem to tackle.
b.AssertFileContent("public/tags/index.html", "All. Tag1|Tag2|")
}
func TestRebuildEditNonReferencedResourceIssue13748(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
baseURL = "https://example.com"
disableLiveReload = true
-- content/mybundle/index.md --
-- content/mybundle/resource.txt --
This is a resource file.
-- layouts/all.html --
All.
`
b := TestRunning(t, files)
b.AssertFileContent("public/mybundle/resource.txt", "This is a resource file.")
b.EditFileReplaceAll("content/mybundle/resource.txt", "This is a resource file.", "This is an edited resource file.").Build()
b.AssertFileContent("public/mybundle/resource.txt", "This is an edited resource file.")
}

View file

@ -398,10 +398,6 @@ func doRenderShortcode(
return true
}
base, layoutDescriptor := po.GetInternalTemplateBasePathAndDescriptor()
// With shortcodes/mymarkdown.md (only), this allows {{% mymarkdown %}} when rendering HTML,
// but will not resolve any template when doing {{< mymarkdown >}}.
layoutDescriptor.AlwaysAllowPlainText = sc.doMarkup
q := tplimpl.TemplateQuery{
Path: base,
Name: sc.name,
@ -409,9 +405,10 @@ func doRenderShortcode(
Desc: layoutDescriptor,
Consider: include,
}
v, err := s.TemplateStore.LookupShortcode(q)
v := s.TemplateStore.LookupShortcode(q)
if v == nil {
return zeroShortcode, err
s.Log.Errorf("Unable to locate template for shortcode %q in page %q", sc.name, p.File().Path())
return zeroShortcode, nil
}
tmpl = v
hasVariants = hasVariants || len(ofCount) > 1

View file

@ -918,7 +918,7 @@ func TestShortcodeMarkdownOutputFormat(t *testing.T) {
---
title: "p1"
---
{{% foo %}}
{{< foo >}}
# The below would have failed using the HTML template parser.
-- layouts/shortcodes/foo.md --
§§§
@ -930,7 +930,9 @@ title: "p1"
b := Test(t, files)
b.AssertFileContent("public/p1/index.html", "<code>&lt;x")
b.AssertFileContent("public/p1/index.html", `
<x
`)
}
func TestShortcodePreserveIndentation(t *testing.T) {

View file

@ -204,7 +204,6 @@ func NewHugoSites(cfg deps.DepsCfg) (*HugoSites, error) {
// Katex is relatively slow.
PoolSize: 8,
Infof: logger.InfoCommand("wasm").Logf,
Warnf: logger.WarnCommand("wasm").Logf,
},
),
}

View file

@ -16,6 +16,7 @@ package hugolib
import (
"bytes"
"fmt"
"io"
"testing"
"github.com/gohugoio/hugo/helpers"
@ -88,11 +89,14 @@ aliases: [/Ali%d]
h.Sites[1].PathSpec.ProcessingStats,
}
stats[0].Table(io.Discard)
stats[1].Table(io.Discard)
var buff bytes.Buffer
helpers.ProcessingStatsTable(&buff, stats...)
c.Assert(buff.String(), qt.Contains, "Pages │ 21 │ 7")
c.Assert(buff.String(), qt.Contains, "Pages | 21 | 7")
}
func TestSiteLastmod(t *testing.T) {

View file

@ -615,7 +615,7 @@ var weightedPage5 = `+++
weight = "5"
title = "Five"
[build]
[_build]
render = "never"
+++
Front Matter with Ordered Pages 5`

View file

@ -1,14 +1,7 @@
# Release env.
# These will be replaced by script before release.
HUGORELEASER_TAG=v0.147.9
HUGORELEASER_COMMITISH=29bdbde19c288d190e889294a862103c6efb70bf
HUGORELEASER_TAG=v0.147.2
HUGORELEASER_COMMITISH=c7feb15d10b29a94d7fb57c31e8bcb2e92718fb7

View file

@ -4,15 +4,6 @@ export function readInput(handle) {
let currentLine = [];
const buffer = new Uint8Array(buffSize);
// These are not implemented by QuickJS.
console.warn = (value) => {
console.log(value);
};
console.error = (value) => {
throw new Error(value);
};
// Read all the available bytes
while (true) {
// Stdin file descriptor

View file

@ -1,2 +1,2 @@
(()=>{function w(r){let e=[],c=new Uint8Array(1024);for(console.warn=n=>{console.log(n)},console.error=n=>{throw new Error(n)};;){let o=0;try{o=Javy.IO.readSync(0,c)}catch(a){if(a.message.includes("os error 29"))break;throw new Error("Error reading from stdin")}if(o<0)throw new Error("Error reading from stdin");if(o===0)break;if(e=[...e,...c.subarray(0,o)],!e.includes(10))continue;let t=0;for(let a=0;t<e.length;t++)if(e[t]===10){let h=e.splice(a,t+1),l=new Uint8Array(h),d;try{d=JSON.parse(new TextDecoder().decode(l))}catch(s){throw new Error(`Error parsing JSON '${new TextDecoder().decode(l)}' from stdin: ${s.message}`)}try{r(d)}catch(s){let u=d.header;u.err=s.message,i({header:u})}a=t+1}e=e.slice(t)}}function i(r){let f=new TextEncoder().encode(JSON.stringify(r)+`
`),e=new Uint8Array(f);Javy.IO.writeSync(1,e)}var g=function(r){i({header:r.header,data:{greeting:"Hello "+r.data.name+"!"}})};console.log("Greet module loaded");w(g);})();
(()=>{function l(r){let e=[],a=new Uint8Array(1024);for(;;){let n=0;try{n=Javy.IO.readSync(0,a)}catch(o){if(o.message.includes("os error 29"))break;throw new Error("Error reading from stdin")}if(n<0)throw new Error("Error reading from stdin");if(n===0)break;if(e=[...e,...a.subarray(0,n)],!e.includes(10))continue;let t=0;for(let o=0;t<e.length;t++)if(e[t]===10){let w=e.splice(o,t+1),f=new Uint8Array(w),c;try{c=JSON.parse(new TextDecoder().decode(f))}catch(d){throw new Error(`Error parsing JSON '${new TextDecoder().decode(f)}' from stdin: ${d.message}`)}try{r(c)}catch(d){let u=c.header;u.err=d.message,i({header:u})}o=t+1}e=e.slice(t)}}function i(r){let s=new TextEncoder().encode(JSON.stringify(r)+`
`),e=new Uint8Array(s);Javy.IO.writeSync(1,e)}var h=function(r){i({header:r.header,data:{greeting:"Hello "+r.data.name+"!"}})};console.log("Greet module loaded");l(h);})();

File diff suppressed because one or more lines are too long

View file

@ -7,16 +7,6 @@ const render = function (input) {
const expression = data.expression;
const options = data.options;
const header = input.header;
header.warnings = [];
if (options.strict == 'warn') {
// By default, KaTeX will write to console.warn, that's a little hard to handle.
options.strict = (errorCode, errorMsg) => {
header.warnings.push(
`katex: LaTeX-incompatible input and strict mode is set to 'warn': ${errorMsg} [${errorCode}]`,
);
};
}
// Any error thrown here will be caught by the common.js readInput function.
const output = katex.renderToString(expression, options);
writeOutput({ header: header, data: { output: output } });

View file

@ -45,7 +45,7 @@ type KatexOptions struct {
// A color string given in the format "#XXX" or "#XXXXXX"
ErrorColor string `json:"errorColor"`
// A collection of custom macros.
// A collection of custom macros.
Macros map[string]string `json:"macros,omitempty"`
// Specifies a minimum thickness, in ems, for fraction lines.
@ -53,22 +53,6 @@ type KatexOptions struct {
// If true, KaTeX will throw a ParseError when it encounters an unsupported command.
ThrowOnError bool `json:"throwOnError"`
// Controls how KaTeX handles LaTeX features that offer convenience but
// aren't officially supported, one of error (default), ignore, or warn.
//
// - error: Throws an error when convenient, unsupported LaTeX features
// are encountered.
// - ignore: Allows convenient, unsupported LaTeX features without any
// feedback.
// - warn: Emits a warning when convenient, unsupported LaTeX features are
// encountered.
//
// The "newLineInDisplayMode" error code, which flags the use of \\
// or \newline in display mode outside an array or tabular environment, is
// intentionally designed not to throw an error, despite this behavior
// being questionable.
Strict string `json:"strict"`
}
type KatexOutput struct {

View file

@ -51,9 +51,6 @@ type Header struct {
// Set in the response if there was an error.
Err string `json:"err"`
// Warnings is a list of warnings that may be returned in the response.
Warnings []string `json:"warnings,omitempty"`
}
type Message[T any] struct {
@ -158,7 +155,6 @@ func (p *dispatcherPool[Q, R]) Execute(ctx context.Context, q Message[Q]) (Messa
}
resp, err := call.response, p.Err()
if err == nil && resp.Header.Err != "" {
err = errors.New(resp.Header.Err)
}
@ -274,8 +270,6 @@ type Options struct {
Infof func(format string, v ...any)
Warnf func(format string, v ...any)
// E.g. quickjs wasm. May be omitted if not needed.
Runtime Binary
@ -331,7 +325,6 @@ type dispatcherPool[Q, R any] struct {
counter atomic.Uint32
dispatchers []*dispatcher[Q, R]
close func() error
opts Options
errc chan error
donec chan struct{}
@ -362,11 +355,6 @@ func newDispatcher[Q, R any](opts Options) (*dispatcherPool[Q, R], error) {
// noop
}
}
if opts.Warnf == nil {
opts.Warnf = func(format string, v ...any) {
// noop
}
}
if opts.Memory <= 0 {
// 32 MiB
@ -478,7 +466,6 @@ func newDispatcher[Q, R any](opts Options) (*dispatcherPool[Q, R], error) {
dp := &dispatcherPool[Q, R]{
dispatchers: make([]*dispatcher[Q, R], len(inOuts)),
opts: opts,
errc: make(chan error, 10),
donec: make(chan struct{}),

Binary file not shown.

Binary file not shown.

View file

@ -104,7 +104,7 @@ func (i Item) ValTyped(source []byte) any {
}
func (i Item) IsText() bool {
return i.Type == tText || i.IsIndentation()
return i.Type == tText || i.Type == tIndentation
}
func (i Item) IsIndentation() bool {
@ -152,7 +152,7 @@ func (i Item) IsFrontMatter() bool {
}
func (i Item) IsDone() bool {
return i.IsError() || i.IsEOF()
return i.Type == tError || i.Type == tEOF
}
func (i Item) IsEOF() bool {
@ -166,19 +166,18 @@ func (i Item) IsError() bool {
func (i Item) ToString(source []byte) string {
val := i.Val(source)
switch {
case i.IsEOF():
case i.Type == tEOF:
return "EOF"
case i.IsError():
case i.Type == tError:
return string(val)
case i.IsIndentation():
case i.Type == tIndentation:
return fmt.Sprintf("%s:[%s]", i.Type, util.VisualizeSpaces(val))
case i.Type > tKeywordMarker:
return fmt.Sprintf("<%s>", val)
case len(val) > 50:
return fmt.Sprintf("%v:%.20q...", i.Type, val)
default:
return fmt.Sprintf("%v:[%s]", i.Type, val)
}
return fmt.Sprintf("%v:[%s]", i.Type, val)
}
type ItemType int

View file

@ -47,217 +47,3 @@ func TestItemValTyped(t *testing.T) {
source = []byte("xtrue")
c.Assert(Item{low: 0, high: len(source)}.ValTyped(source), qt.Equals, "xtrue")
}
func TestItemBoolMethods(t *testing.T) {
c := qt.New(t)
source := []byte(" shortcode ")
tests := []struct {
name string
item Item
source []byte
want bool
call func(Item, []byte) bool
}{
{
name: "IsText true",
item: Item{Type: tText},
call: func(i Item, _ []byte) bool { return i.IsText() },
want: true,
},
{
name: "IsIndentation false",
item: Item{Type: tText},
call: func(i Item, _ []byte) bool { return i.IsIndentation() },
want: false,
},
{
name: "IsShortcodeName",
item: Item{Type: tScName},
call: func(i Item, _ []byte) bool { return i.IsShortcodeName() },
want: true,
},
{
name: "IsNonWhitespace true",
item: Item{
Type: tText,
low: 2,
high: 11,
},
source: source,
call: func(i Item, src []byte) bool { return i.IsNonWhitespace(src) },
want: true,
},
{
name: "IsShortcodeParam false",
item: Item{Type: tScParamVal},
call: func(i Item, _ []byte) bool { return i.IsShortcodeParam() },
want: false,
},
{
name: "IsInlineShortcodeName",
item: Item{Type: tScNameInline},
call: func(i Item, _ []byte) bool { return i.IsInlineShortcodeName() },
want: true,
},
{
name: "IsLeftShortcodeDelim tLeftDelimScWithMarkup",
item: Item{Type: tLeftDelimScWithMarkup},
call: func(i Item, _ []byte) bool { return i.IsLeftShortcodeDelim() },
want: true,
},
{
name: "IsLeftShortcodeDelim tLeftDelimScNoMarkup",
item: Item{Type: tLeftDelimScNoMarkup},
call: func(i Item, _ []byte) bool { return i.IsLeftShortcodeDelim() },
want: true,
},
{
name: "IsRightShortcodeDelim tRightDelimScWithMarkup",
item: Item{Type: tRightDelimScWithMarkup},
call: func(i Item, _ []byte) bool { return i.IsRightShortcodeDelim() },
want: true,
},
{
name: "IsRightShortcodeDelim tRightDelimScNoMarkup",
item: Item{Type: tRightDelimScNoMarkup},
call: func(i Item, _ []byte) bool { return i.IsRightShortcodeDelim() },
want: true,
},
{
name: "IsShortcodeClose",
item: Item{Type: tScClose},
call: func(i Item, _ []byte) bool { return i.IsShortcodeClose() },
want: true,
},
{
name: "IsShortcodeParamVal",
item: Item{Type: tScParamVal},
call: func(i Item, _ []byte) bool { return i.IsShortcodeParamVal() },
want: true,
},
{
name: "IsShortcodeMarkupDelimiter tLeftDelimScWithMarkup",
item: Item{Type: tLeftDelimScWithMarkup},
call: func(i Item, _ []byte) bool { return i.IsShortcodeMarkupDelimiter() },
want: true,
},
{
name: "IsShortcodeMarkupDelimiter tRightDelimScWithMarkup",
item: Item{Type: tRightDelimScWithMarkup},
call: func(i Item, _ []byte) bool { return i.IsShortcodeMarkupDelimiter() },
want: true,
},
{
name: "IsFrontMatter TypeFrontMatterYAML",
item: Item{Type: TypeFrontMatterYAML},
call: func(i Item, _ []byte) bool { return i.IsFrontMatter() },
want: true,
},
{
name: "IsFrontMatter TypeFrontMatterTOML",
item: Item{Type: TypeFrontMatterTOML},
call: func(i Item, _ []byte) bool { return i.IsFrontMatter() },
want: true,
},
{
name: "IsFrontMatter TypeFrontMatterJSON",
item: Item{Type: TypeFrontMatterJSON},
call: func(i Item, _ []byte) bool { return i.IsFrontMatter() },
want: true,
},
{
name: "IsFrontMatter TypeFrontMatterORG",
item: Item{Type: TypeFrontMatterORG},
call: func(i Item, _ []byte) bool { return i.IsFrontMatter() },
want: true,
},
{
name: "IsDone tError",
item: Item{Type: tError},
call: func(i Item, _ []byte) bool { return i.IsDone() },
want: true,
},
{
name: "IsDone tEOF",
item: Item{Type: tEOF},
call: func(i Item, _ []byte) bool { return i.IsDone() },
want: true,
},
{
name: "IsEOF",
item: Item{Type: tEOF},
call: func(i Item, _ []byte) bool { return i.IsEOF() },
want: true,
},
{
name: "IsError",
item: Item{Type: tError},
call: func(i Item, _ []byte) bool { return i.IsError() },
want: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.call(tt.item, tt.source)
c.Assert(got, qt.Equals, tt.want)
})
}
}
func TestItem_ToString(t *testing.T) {
c := qt.New(t)
source := []byte("src")
long := make([]byte, 100)
for i := range long {
long[i] = byte(i)
}
tests := []struct {
name string
item Item
source []byte
want string
call func(Item, []byte) string
}{
{
name: "EOF",
item: Item{Type: tEOF},
call: func(i Item, _ []byte) string { return i.ToString(source) },
want: "EOF",
},
{
name: "Error",
item: Item{Type: tError},
call: func(i Item, _ []byte) string { return i.ToString(source) },
want: "",
},
{
name: "Indentation",
item: Item{Type: tIndentation},
call: func(i Item, _ []byte) string { return i.ToString(source) },
want: "tIndentation:[]",
},
{
name: "Long",
item: Item{Type: tKeywordMarker + 1, low: 0, high: 100},
call: func(i Item, _ []byte) string { return i.ToString(long) },
want: "<" + string(long) + ">",
},
{
name: "Empty",
item: Item{Type: tKeywordMarker + 1},
call: func(i Item, _ []byte) string { return i.ToString([]byte("")) },
want: "<>",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := tt.call(tt.item, tt.source)
c.Assert(got, qt.Equals, tt.want)
})
}
}

View file

@ -105,9 +105,9 @@ func CheckCascadePattern(logger loggers.Logger, m PageMatcher) {
}
}
func DecodeCascadeConfig(logger loggers.Logger, handleLegacyFormat bool, in any) (*config.ConfigNamespace[[]PageMatcherParamsConfig, *maps.Ordered[PageMatcher, PageMatcherParamsConfig]], error) {
buildConfig := func(in any) (*maps.Ordered[PageMatcher, PageMatcherParamsConfig], any, error) {
cascade := maps.NewOrdered[PageMatcher, PageMatcherParamsConfig]()
func DecodeCascadeConfig(logger loggers.Logger, handleLegacyFormat bool, in any) (*config.ConfigNamespace[[]PageMatcherParamsConfig, *maps.Ordered[PageMatcher, maps.Params]], error) {
buildConfig := func(in any) (*maps.Ordered[PageMatcher, maps.Params], any, error) {
cascade := maps.NewOrdered[PageMatcher, maps.Params]()
if in == nil {
return cascade, []map[string]any{}, nil
}
@ -124,7 +124,11 @@ func DecodeCascadeConfig(logger loggers.Logger, handleLegacyFormat bool, in any)
c PageMatcherParamsConfig
err error
)
c, err = mapToPageMatcherParamsConfig(m)
if handleLegacyFormat {
c, err = mapToPageMatcherParamsConfigLegacy(m)
} else {
c, err = mapToPageMatcherParamsConfig(m)
}
if err != nil {
return nil, nil, err
}
@ -143,28 +147,23 @@ func DecodeCascadeConfig(logger loggers.Logger, handleLegacyFormat bool, in any)
if found {
// Merge
for k, v := range cfg.Params {
if _, found := c.Params[k]; !found {
c.Params[k] = v
}
}
for k, v := range cfg.Fields {
if _, found := c.Fields[k]; !found {
c.Fields[k] = v
if _, found := c[k]; !found {
c[k] = v
}
}
} else {
cascade.Set(m, cfg)
cascade.Set(m, cfg.Params)
}
}
return cascade, cfgs, nil
}
return config.DecodeNamespace[[]PageMatcherParamsConfig, *maps.Ordered[PageMatcher, PageMatcherParamsConfig]](in, buildConfig)
return config.DecodeNamespace[[]PageMatcherParamsConfig, *maps.Ordered[PageMatcher, maps.Params]](in, buildConfig)
}
// DecodeCascade decodes in which could be either a map or a slice of maps.
func DecodeCascade(logger loggers.Logger, handleLegacyFormat bool, in any) (*maps.Ordered[PageMatcher, PageMatcherParamsConfig], error) {
func DecodeCascade(logger loggers.Logger, handleLegacyFormat bool, in any) (*maps.Ordered[PageMatcher, maps.Params], error) {
conf, err := DecodeCascadeConfig(logger, handleLegacyFormat, in)
if err != nil {
return nil, err
@ -174,9 +173,6 @@ func DecodeCascade(logger loggers.Logger, handleLegacyFormat bool, in any) (*map
func mapToPageMatcherParamsConfig(m map[string]any) (PageMatcherParamsConfig, error) {
var pcfg PageMatcherParamsConfig
if pcfg.Fields == nil {
pcfg.Fields = make(maps.Params)
}
for k, v := range m {
switch strings.ToLower(k) {
case "_target", "target":
@ -185,19 +181,47 @@ func mapToPageMatcherParamsConfig(m map[string]any) (PageMatcherParamsConfig, er
return pcfg, err
}
pcfg.Target = target
case "params":
default:
if pcfg.Params == nil {
pcfg.Params = make(maps.Params)
}
pcfg.Params[k] = v
}
}
return pcfg, pcfg.init()
}
func mapToPageMatcherParamsConfigLegacy(m map[string]any) (PageMatcherParamsConfig, error) {
var pcfg PageMatcherParamsConfig
for k, v := range m {
switch strings.ToLower(k) {
case "params":
// We simplified the structure of the cascade config in Hugo 0.111.0.
// There is a small chance that someone has used the old structure with the params keyword,
// those values will now be moved to the top level.
// This should be very unlikely as it would lead to constructs like .Params.params.foo,
// and most people see params as an Hugo internal keyword.
params := maps.ToStringMap(v)
for k, v := range params {
if _, found := pcfg.Params[k]; !found {
pcfg.Params[k] = v
if pcfg.Params == nil {
pcfg.Params = params
} else {
for k, v := range params {
if _, found := pcfg.Params[k]; !found {
pcfg.Params[k] = v
}
}
}
case "_target", "target":
var target PageMatcher
if err := decodePageMatcher(v, &target); err != nil {
return pcfg, err
}
pcfg.Target = target
default:
pcfg.Fields[k] = v
if pcfg.Params == nil {
pcfg.Params = make(maps.Params)
}
pcfg.Params[k] = v
}
}
return pcfg, pcfg.init()
@ -226,14 +250,10 @@ func decodePageMatcher(m any, v *PageMatcher) error {
type PageMatcherParamsConfig struct {
// Apply Params to all Pages matching Target.
Params maps.Params
// Fields holds all fields but Params.
Fields maps.Params
// Target is the PageMatcher that this config applies to.
Target PageMatcher
}
func (p *PageMatcherParamsConfig) init() error {
maps.PrepareParams(p.Params)
maps.PrepareParams(p.Fields)
return nil
}

View file

@ -84,22 +84,23 @@ func TestPageMatcher(t *testing.T) {
c.Run("mapToPageMatcherParamsConfig", func(c *qt.C) {
fn := func(m map[string]any) PageMatcherParamsConfig {
v, err := mapToPageMatcherParamsConfig(m)
v, err := mapToPageMatcherParamsConfigLegacy(m)
c.Assert(err, qt.IsNil)
return v
}
// Legacy.
c.Assert(fn(map[string]any{"_target": map[string]any{"kind": "page"}, "foo": "bar"}), qt.DeepEquals, PageMatcherParamsConfig{
Fields: maps.Params{
Params: maps.Params{
"foo": "bar",
},
Target: PageMatcher{Path: "", Kind: "page", Lang: "", Environment: ""},
})
// Current format.
c.Assert(fn(map[string]any{"target": map[string]any{"kind": "page"}, "params": map[string]any{"foo": "bar"}}), qt.DeepEquals, PageMatcherParamsConfig{
Params: maps.Params{
"foo": "bar",
},
Fields: maps.Params{},
Target: PageMatcher{Path: "", Kind: "page", Lang: "", Environment: ""},
})
})
@ -133,14 +134,13 @@ func TestDecodeCascadeConfig(t *testing.T) {
c.Assert(err, qt.IsNil)
c.Assert(got, qt.IsNotNil)
c.Assert(got.Config.Keys(), qt.DeepEquals, []PageMatcher{{Kind: "page", Environment: "production"}, {Kind: "page"}})
c.Assert(got.Config.Values(), qt.DeepEquals, []maps.Params{{"a": string("av")}, {"b": string("bv")}})
c.Assert(got.SourceStructure, qt.DeepEquals, []PageMatcherParamsConfig{
{
Params: maps.Params{"a": string("av")},
Fields: maps.Params{},
Target: PageMatcher{Kind: "page", Environment: "production"},
},
{Params: maps.Params{"b": string("bv")}, Fields: maps.Params{}, Target: PageMatcher{Kind: "page"}},
{Params: maps.Params{"b": string("bv")}, Target: PageMatcher{Kind: "page"}},
})
got, err = DecodeCascadeConfig(loggers.NewDefault(), true, nil)

View file

@ -125,10 +125,10 @@ type PageConfig struct {
ContentAdapterData map[string]any `mapstructure:"-" json:"-"`
// Compiled values.
CascadeCompiled *maps.Ordered[page.PageMatcher, page.PageMatcherParamsConfig] `mapstructure:"-" json:"-"`
ContentMediaType media.Type `mapstructure:"-" json:"-"`
ConfiguredOutputFormats output.Formats `mapstructure:"-" json:"-"`
IsFromContentAdapter bool `mapstructure:"-" json:"-"`
CascadeCompiled *maps.Ordered[page.PageMatcher, maps.Params] `mapstructure:"-" json:"-"`
ContentMediaType media.Type `mapstructure:"-" json:"-"`
ConfiguredOutputFormats output.Formats `mapstructure:"-" json:"-"`
IsFromContentAdapter bool `mapstructure:"-" json:"-"`
}
func ClonePageConfigForRebuild(p *PageConfig, params map[string]any) *PageConfig {

View file

@ -31,7 +31,7 @@ func TestDecodeBuildConfig(t *testing.T) {
c := qt.New(t)
configTempl := `
[build]
[_build]
render = %s
list = %s
publishResources = true`
@ -82,7 +82,7 @@ publishResources = true`
} {
cfg, err := config.FromConfigString(fmt.Sprintf(configTempl, test.args...), "toml")
c.Assert(err, qt.IsNil)
bcfg, err := DecodeBuildConfig(cfg.Get("build"))
bcfg, err := DecodeBuildConfig(cfg.Get("_build"))
c.Assert(err, qt.IsNil)
eq := qt.CmpEquals(hqt.DeepAllowUnexported(BuildConfig{}))

View file

@ -311,7 +311,7 @@ func (l PermalinkExpander) pageToPermalinkSections(p Page, _ string) (string, er
// pageToPermalinkContentBaseName returns the URL-safe form of the content base name.
func (l PermalinkExpander) pageToPermalinkContentBaseName(p Page, _ string) (string, error) {
return l.urlize(p.PathInfo().Unnormalized().BaseNameNoIdentifier()), nil
return l.urlize(p.PathInfo().BaseNameNoIdentifier()), nil
}
// pageToPermalinkSlugOrContentBaseName returns the URL-safe form of the slug, content base name.

View file

@ -14,7 +14,6 @@
package page_test
import (
"strings"
"testing"
"github.com/bep/logg"
@ -344,29 +343,3 @@ slug: "c2slug"
b.AssertFileContent("public/myc/c1/index.html", "C1|/myc/c1/|term|")
b.AssertFileContent("public/myc/c2slug/index.html", "C2|/myc/c2slug/|term|")
}
func TestIssue13755(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['home','rss','section','sitemap','taxonomy','term']
disablePathToLower = false
[permalinks.page]
s1 = "/:contentbasename"
-- content/s1/aBc.md --
---
title: aBc
---
-- layouts/all.html --
{{ .Title }}
`
b := hugolib.Test(t, files)
b.AssertFileExists("public/abc/index.html", true)
files = strings.ReplaceAll(files, "disablePathToLower = false", "disablePathToLower = true")
b = hugolib.Test(t, files)
b.AssertFileExists("public/aBc/index.html", true)
}

View file

@ -24,7 +24,6 @@ import (
"sync/atomic"
"github.com/gohugoio/hugo/identity"
"github.com/gohugoio/hugo/lazy"
"github.com/gohugoio/hugo/resources/internal"
"github.com/gohugoio/hugo/common/hashing"
@ -55,7 +54,6 @@ var (
_ identity.DependencyManagerProvider = (*genericResource)(nil)
_ identity.Identity = (*genericResource)(nil)
_ fileInfo = (*genericResource)(nil)
_ isPublishedProvider = (*genericResource)(nil)
)
type ResourceSourceDescriptor struct {
@ -244,7 +242,6 @@ type baseResourceInternal interface {
fileInfo
mediaTypeAssigner
targetPather
isPublishedProvider
ReadSeekCloser() (hugio.ReadSeekCloser, error)
@ -358,7 +355,7 @@ func GetTestInfoForResource(r resource.Resource) GenericResourceTestInfo {
// genericResource represents a generic linkable resource.
type genericResource struct {
publishInit *lazy.OnceMore
publishInit *sync.Once
key string
keyInit *sync.Once
@ -539,10 +536,6 @@ func (l *genericResource) Publish() error {
return err
}
func (l *genericResource) isPublished() bool {
return l.publishInit.Done()
}
func (l *genericResource) RelPermalink() string {
return l.spec.PathSpec.GetBasePath(false) + paths.PathEscape(l.paths.TargetLink())
}
@ -636,7 +629,7 @@ func (rc *genericResource) cloneWithUpdates(u *transformationUpdate) (baseResour
}
func (l genericResource) clone() *genericResource {
l.publishInit = &lazy.OnceMore{}
l.publishInit = &sync.Once{}
l.keyInit = &sync.Once{}
return &l
}
@ -650,10 +643,6 @@ type targetPather interface {
TargetPath() string
}
type isPublishedProvider interface {
isPublished() bool
}
type resourceHash struct {
value uint64
size int64
@ -713,11 +702,6 @@ func InternalResourceSourcePathBestEffort(r resource.Resource) string {
return InternalResourceTargetPath(r)
}
// isPublished returns true if the resource is published.
func IsPublished(r resource.Resource) bool {
return r.(isPublishedProvider).isPublished()
}
type targetPathProvider interface {
// targetPath is the relative path to this resource.
// In most cases this will be the same as the RelPermalink(),

View file

@ -81,6 +81,11 @@ type ResourceWithoutMeta interface {
ResourceDataProvider
}
type ResourceWrapper interface {
UnwrappedResource() Resource
WrapResource(Resource) ResourceWrapper
}
type ResourceTypeProvider interface {
// ResourceType is the resource type. For most file types, this is the main
// part of the MIME type, e.g. "image", "application", "text" etc.

View file

@ -20,7 +20,6 @@ import (
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/config/allconfig"
"github.com/gohugoio/hugo/lazy"
"github.com/gohugoio/hugo/output"
"github.com/gohugoio/hugo/resources/internal"
"github.com/gohugoio/hugo/resources/jsconfig"
@ -190,7 +189,7 @@ func (r *Spec) NewResource(rd ResourceSourceDescriptor) (resource.Resource, erro
gr := &genericResource{
Staler: &AtomicStaler{},
h: &resourceHash{},
publishInit: &lazy.OnceMore{},
publishInit: &sync.Once{},
keyInit: &sync.Once{},
includeHashInKey: isImage,
paths: rp,

View file

@ -69,6 +69,7 @@ func (c *PostCSSClient) Process(res resources.ResourceTransformer, options map[s
}
type InlineImports struct {
// Service `mapstructure:",squash"`
// Enable inlining of @import statements.
// Does so recursively, but currently once only per file;
// that is, it's not possible to import the same file in
@ -77,11 +78,6 @@ type InlineImports struct {
// so you can have @import anywhere in the file.
InlineImports bool
// See issue https://github.com/gohugoio/hugo/issues/13719
// Disable inlining of @import statements
// This is currenty only used for css.TailwindCSS.
DisableInlineImports bool
// When InlineImports is enabled, we fail the build if an import cannot be resolved.
// You can enable this to allow the build to continue and leave the import statement in place.
// Note that the inline importer does not process url location or imports with media queries,

View file

@ -129,11 +129,9 @@ func (t *tailwindcssTransformation) Transform(ctx *resources.ResourceTransformat
t.rs.Assets.Fs, t.rs.Logger, ctx.DependencyManager,
)
if !options.InlineImports.DisableInlineImports {
src, err = imp.resolve()
if err != nil {
return err
}
src, err = imp.resolve()
if err != nil {
return err
}
go func() {
@ -148,11 +146,7 @@ func (t *tailwindcssTransformation) Transform(ctx *resources.ResourceTransformat
Cause: err,
}
}
s := errBuf.String()
if options.InlineImports.DisableInlineImports && strings.Contains(s, "Can't resolve") {
s += "You may want to set the 'disableInlineImports' option to false to inline imports, see https://gohugo.io/functions/css/tailwindcss/#disableinlineimports"
}
return imp.toFileError(s)
return imp.toFileError(errBuf.String())
}
return nil

View file

@ -17,7 +17,6 @@ import (
"testing"
"github.com/bep/logg"
qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/htesting"
"github.com/gohugoio/hugo/hugolib"
)
@ -71,66 +70,3 @@ CSS: {{ $css.Content | safeCSS }}|
b.AssertFileContent("public/index.html", "/*! tailwindcss v4.")
}
func TestTailwindCSSNoInlineImportsIssue13719(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['page','rss','section','sitemap','taxonomy','term']
theme = 'my-theme'
[[module.mounts]]
source = 'assets'
target = 'assets'
[[module.mounts]]
source = 'other'
target = 'assets/css'
-- assets/css/main.css --
@import "tailwindcss";
@import "colors/red.css";
@import "colors/blue.css";
@import "colors/purple.css";
-- assets/css/colors/red.css --
@import "green.css";
.red {color: red;}
-- assets/css/colors/green.css --
.green {color: green;}
-- themes/my-theme/assets/css/colors/blue.css --
.blue {color: blue;}
-- other/colors/purple.css --
.purple {color: purple;}
-- layouts/home.html --
{{ with (templates.Defer (dict "key" "global")) }}
{{ with resources.Get "css/main.css" }}
{{ $opts := dict "disableInlineImports" true }}
{{ with . | css.TailwindCSS $opts }}
<link rel="stylesheet" href="{{ .RelPermalink }}">
{{ end }}
{{ end }}
{{ end }}
-- package.json --
{
"devDependencies": {
"@tailwindcss/cli": "^4.1.7",
"tailwindcss": "^4.1.7"
}
}
`
b, err := hugolib.NewIntegrationTestBuilder(
hugolib.IntegrationTestConfig{
T: t,
TxtarString: files,
NeedsOsFS: true,
NeedsNpmInstall: true,
LogLevel: logg.LevelInfo,
}).BuildE()
b.Assert(err, qt.IsNotNil)
b.Assert(err.Error(), qt.Contains, "Can't resolve 'colors/red.css'")
b.Assert(err.Error(), qt.Contains, "You may want to set the 'disableInlineImports' option to false")
}

View file

@ -61,7 +61,6 @@ var (
_ identity.DependencyManagerProvider = (*resourceAdapter)(nil)
_ identity.IdentityGroupProvider = (*resourceAdapter)(nil)
_ resource.NameNormalizedProvider = (*resourceAdapter)(nil)
_ isPublishedProvider = (*resourceAdapter)(nil)
)
// These are transformations that need special support in Hugo that may not
@ -326,11 +325,6 @@ func (r *resourceAdapter) Publish() error {
return r.target.Publish()
}
func (r *resourceAdapter) isPublished() bool {
r.init(false, false)
return r.target.isPublished()
}
func (r *resourceAdapter) ReadSeekCloser() (hugio.ReadSeekCloser, error) {
r.init(false, false)
return r.target.ReadSeekCloser()

View file

@ -15,7 +15,6 @@ package template
import (
"fmt"
"iter"
"github.com/gohugoio/hugo/common/types"
template "github.com/gohugoio/hugo/tpl/internal/go_templates/texttemplate"
@ -39,19 +38,6 @@ func (t *Template) Prepare() (*template.Template, error) {
return t.text, nil
}
func (t *Template) All() iter.Seq[*Template] {
return func(yield func(t *Template) bool) {
ns := t.nameSpace
ns.mu.Lock()
defer ns.mu.Unlock()
for _, v := range ns.set {
if !yield(v) {
return
}
}
}
}
// See https://github.com/golang/go/issues/5884
func StripTags(html string) string {
return stripTags(html)

View file

@ -17,7 +17,6 @@ import (
"context"
"fmt"
"io"
"iter"
"reflect"
"github.com/gohugoio/hugo/common/herrors"
@ -434,18 +433,3 @@ func (s *state) evalCall(dot, fun reflect.Value, isBuiltin bool, node parse.Node
func isTrue(val reflect.Value) (truth, ok bool) {
return hreflect.IsTruthfulValue(val), true
}
func (t *Template) All() iter.Seq[*Template] {
return func(yield func(t *Template) bool) {
if t.common == nil {
return
}
t.muTmpl.RLock()
defer t.muTmpl.RUnlock()
for _, v := range t.tmpl {
if !yield(v) {
return
}
}
}
}

View file

@ -533,7 +533,7 @@ func (t *Tree) parseControl(context string) (pos Pos, line int, pipe *PipeNode,
t.rangeDepth--
}
switch next.Type() {
case nodeEnd: // done
case nodeEnd: //done
case nodeElse:
// Special case for "else if" and "else with".
// If the "else" is followed immediately by an "if" or "with",

View file

@ -258,7 +258,7 @@ func TestMod(t *testing.T) {
{int32(3), int32(2), int64(1)},
{int64(3), int64(2), int64(1)},
{"3", "2", int64(1)},
{"3.1", "2", int64(1)},
{"3.1", "2", false},
{"aaa", "0", false},
{"3", "aaa", false},
} {
@ -304,7 +304,7 @@ func TestModBool(t *testing.T) {
{int64(3), int64(2), false},
{"3", "3", true},
{"3", "2", false},
{"3.1", "2", false},
{"3.1", "2", nil},
{"aaa", "0", nil},
{"3", "aaa", nil},
} {

View file

@ -133,7 +133,7 @@ func (ns *Namespace) lookup(name string) (*tplimpl.TemplInfo, error) {
if strings.HasPrefix(name, "partials/") {
// This is most likely not what the user intended.
// This worked before Hugo 0.146.0.
ns.deps.Log.Warnidf(constants.WarnPartialSuperfluousPrefix, "Doubtful use of partial function in {{ partial \"%s\"}}), this is most likely not what you want. Consider removing superfluous prefix \"partials/\" from template name given as first function argument.", name)
ns.deps.Log.Warnidf(constants.WarnPartialSuperfluousPrefix, "Partial name %q starting with 'partials/' (as in {{ partial \"%s\"}}) is most likely not what you want. Before 0.146.0 we did a double lookup in this situation.", name, name)
}
v := ns.deps.TemplateStore.LookupPartial(name)
if v == nil {

View file

@ -20,7 +20,7 @@
{{- $request := printf "https://publish.twitter.com/oembed?%s" $query -}}
{{- with try (resources.GetRemote $request) -}}
{{- with .Err -}}
{{- warnidf "shortcode-twitter-getremote" "The %q shortcode was unable to retrieve the remote data: %s. See %s" $.ctx.Name . $.ctx.Position -}}
{{- errorf "%s" . -}}
{{- else with .Value -}}
{{- (. | transform.Unmarshal).html | safeHTML -}}
{{- else -}}

View file

@ -16,7 +16,7 @@
{{- $request := printf "https://publish.twitter.com/oembed?%s" $query -}}
{{- with try (resources.GetRemote $request) -}}
{{- with .Err -}}
{{- warnidf "shortcode-twitter-simple-getremote" "The %q shortcode was unable to retrieve the remote data: %s. See %s" $.ctx.Name . $.ctx.Position -}}
{{- errorf "%s" . -}}
{{- else with .Value -}}
{{- if not site.Config.Services.Twitter.DisableInlineCSS }}
{{- template "__h_simple_twitter_css" (dict "ctx" $.ctx) }}

View file

@ -25,7 +25,7 @@
{{- $request := printf "https://vimeo.com/api/oembed.json?%s" $query -}}
{{- with try (resources.GetRemote $request) -}}
{{- with .Err -}}
{{- warnidf "shortcode-vimeo-simple" "The %q shortcode was unable to retrieve the remote data: %s. See %s" $.ctx.Name . $.ctx.Position -}}
{{- errorf "%s" . -}}
{{- else with .Value -}}
{{- with . | transform.Unmarshal -}}
{{- $class := printf "%s %s" "s_video_simple" "__h_video" -}}

View file

@ -19,7 +19,7 @@
{{- $request := printf "https://publish.x.com/oembed?%s" $query -}}
{{- with try (resources.GetRemote $request) -}}
{{- with .Err -}}
{{- warnidf "shortcode-x-getremote" "The %q shortcode was unable to retrieve the remote data: %s. See %s" $.ctx.Name . $.ctx.Position -}}
{{- errorf "%s" . -}}
{{- else with .Value -}}
{{- (. | transform.Unmarshal).html | safeHTML -}}
{{- else -}}

View file

@ -15,7 +15,7 @@
{{- $request := printf "https://publish.x.com/oembed?%s" $query -}}
{{- with try (resources.GetRemote $request) -}}
{{- with .Err -}}
{{- warnidf "shortcode-x-simple-getremote" "The %q shortcode was unable to retrieve the remote data: %s. See %s" $.ctx.Name . $.ctx.Position -}}
{{- errorf "%s" . -}}
{{- else with .Value -}}
{{- if not site.Config.Services.X.DisableInlineCSS }}
{{- template "__h_simple_x_css" (dict "ctx" $.ctx) }}

View file

@ -17,7 +17,6 @@ import (
"strings"
"testing"
qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/htesting/hqt"
"github.com/gohugoio/hugo/hugolib"
)
@ -697,100 +696,3 @@ title: p2
b.AssertFileContent("public/p1/index.html", "78eb19b5c6f3768f")
b.AssertFileContent("public/p2/index.html", "a6db910a9cf54bc1")
}
func TestShortcodePlainTextVsHTMLTemplateIssue13698(t *testing.T) {
t.Parallel()
filesTemplate := `
-- hugo.toml --
markup.goldmark.renderer.unsafe = true
-- layouts/all.html --
Content: {{ .Content }}|
-- layouts/_shortcodes/mymarkdown.md --
<div>Foo bar</div>
-- content/p1.md --
---
title: p1
---
## A shortcode
SHORTCODE
`
files := strings.ReplaceAll(filesTemplate, "SHORTCODE", "{{% mymarkdown %}}")
b := hugolib.Test(t, files)
b.AssertFileContent("public/p1/index.html", "<div>Foo bar</div>")
files = strings.ReplaceAll(filesTemplate, "SHORTCODE", "{{< mymarkdown >}}")
var err error
b, err = hugolib.TestE(t, files)
b.Assert(err, qt.IsNotNil)
b.Assert(err.Error(), qt.Contains, `no compatible template found for shortcode "mymarkdown" in [/_shortcodes/mymarkdown.md]; note that to use plain text template shortcodes in HTML you need to use the shortcode {{% delimiter`)
}
func TestShortcodeOnlyLanguageInBaseIssue13699And13740(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
baseURL = 'https://example.org/'
disableLanguages = ['de']
[languages]
[languages.en]
weight = 1
[languages.de]
weight = 2
-- layouts/_shortcodes/de.html --
de.html
-- layouts/all.html --
{{ .Content }}
-- content/_index.md --
---
title: home
---
{{< de >}}
`
b := hugolib.Test(t, files)
b.AssertFileContent("public/index.html", "de.html")
}
func TestShortcodeLanguage13767(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
defaultContentLanguage = 'pl'
defaultContentLanguageInSubdir = true
[languages.pl]
weight = 1
[languages.en]
weight = 2
-- content/_index.md --
---
title: dom
---
{{< myshortcode >}}
-- content/_index.en.md --
---
title: home
---
{{< myshortcode >}}
-- layouts/_shortcodes/myshortcode.html --
myshortcode.html
-- layouts/_shortcodes/myshortcode.en.html --
myshortcode.en.html
-- layouts/all.html --
{{ .Content }}
`
b := hugolib.Test(t, files)
b.AssertFileContent("public/pl/index.html", "myshortcode.html")
b.AssertFileContent("public/en/index.html", "myshortcode.en.html")
}

View file

@ -37,7 +37,6 @@ type TemplateDescriptor struct {
// Misc.
LayoutFromUserMustMatch bool // If set, we only look for the exact layout.
IsPlainText bool // Whether this is a plain text template.
AlwaysAllowPlainText bool // Whether to e.g. allow plain text templates to be rendered in HTML.
}
func (d *TemplateDescriptor) normalizeFromFile() {
@ -65,7 +64,7 @@ func (s descriptorHandler) compareDescriptors(category Category, isEmbedded bool
return weightNoMatch
}
w := this.doCompare(category, s.opts.DefaultContentLanguage, other)
w := this.doCompare(category, isEmbedded, s.opts.DefaultContentLanguage, other)
if w.w1 <= 0 {
if category == CategoryMarkup && (this.Variant1 == other.Variant1) && (this.Variant2 == other.Variant2 || this.Variant2 != "" && other.Variant2 == "") {
@ -75,12 +74,7 @@ func (s descriptorHandler) compareDescriptors(category Category, isEmbedded bool
}
w.w1 = 1
}
if category == CategoryShortcode {
if (this.IsPlainText == other.IsPlainText || !other.IsPlainText) || this.AlwaysAllowPlainText {
w.w1 = 1
}
return w
}
}
@ -88,16 +82,13 @@ func (s descriptorHandler) compareDescriptors(category Category, isEmbedded bool
}
//lint:ignore ST1006 this vs other makes it easier to reason about.
func (this TemplateDescriptor) doCompare(category Category, defaultContentLanguage string, other TemplateDescriptor) weight {
func (this TemplateDescriptor) doCompare(category Category, isEmbedded bool, defaultContentLanguage string, other TemplateDescriptor) weight {
w := weightNoMatch
if !this.AlwaysAllowPlainText {
// HTML in plain text is OK, but not the other way around.
if other.IsPlainText && !this.IsPlainText {
return w
}
// HTML in plain text is OK, but not the other way around.
if other.IsPlainText && !this.IsPlainText {
return w
}
if other.Kind != "" && other.Kind != this.Kind {
return w
}

View file

@ -2,7 +2,6 @@ package tplimpl
import (
"io"
"iter"
"regexp"
"strconv"
"strings"
@ -45,15 +44,16 @@ var embeddedTemplatesAliases = map[string][]string{
"_shortcodes/twitter.html": {"_shortcodes/tweet.html"},
}
func (s *TemplateStore) parseTemplate(ti *TemplInfo, replace bool) error {
err := s.tns.doParseTemplate(ti, replace)
func (s *TemplateStore) parseTemplate(ti *TemplInfo) error {
err := s.tns.doParseTemplate(ti)
if err != nil {
return s.addFileContext(ti, "parse of template failed", err)
}
return err
}
func (t *templateNamespace) doParseTemplate(ti *TemplInfo, replace bool) error {
func (t *templateNamespace) doParseTemplate(ti *TemplInfo) error {
if !ti.noBaseOf || ti.category == CategoryBaseof {
// Delay parsing until we have the base template.
return nil
@ -68,7 +68,7 @@ func (t *templateNamespace) doParseTemplate(ti *TemplInfo, replace bool) error {
if ti.D.IsPlainText {
prototype := t.parseText
if !replace && prototype.Lookup(name) != nil {
if prototype.Lookup(name) != nil {
name += "-" + strconv.FormatUint(t.nameCounter.Add(1), 10)
}
templ, err = prototype.New(name).Parse(ti.content)
@ -77,7 +77,7 @@ func (t *templateNamespace) doParseTemplate(ti *TemplInfo, replace bool) error {
}
} else {
prototype := t.parseHTML
if !replace && prototype.Lookup(name) != nil {
if prototype.Lookup(name) != nil {
name += "-" + strconv.FormatUint(t.nameCounter.Add(1), 10)
}
templ, err = prototype.New(name).Parse(ti.content)
@ -181,24 +181,19 @@ func (t *templateNamespace) applyBaseTemplate(overlay *TemplInfo, base keyTempla
return nil
}
func (t *templateNamespace) templatesIn(in tpl.Template) iter.Seq[tpl.Template] {
return func(yield func(t tpl.Template) bool) {
switch in := in.(type) {
case *htmltemplate.Template:
for t := range in.All() {
if !yield(t) {
return
}
}
case *texttemplate.Template:
for t := range in.All() {
if !yield(t) {
return
}
}
func (t *templateNamespace) templatesIn(in tpl.Template) []tpl.Template {
var templs []tpl.Template
if textt, ok := in.(*texttemplate.Template); ok {
for _, t := range textt.Templates() {
templs = append(templs, t)
}
}
if htmlt, ok := in.(*htmltemplate.Template); ok {
for _, t := range htmlt.Templates() {
templs = append(templs, t)
}
}
return templs
}
/*
@ -342,6 +337,8 @@ func (t *templateNamespace) createPrototypes(init bool) error {
t.prototypeHTML = htmltemplate.Must(t.parseHTML.Clone())
t.prototypeText = texttemplate.Must(t.parseText.Clone())
}
// t.execHTML = htmltemplate.Must(t.parseHTML.Clone())
// t.execText = texttemplate.Must(t.parseText.Clone())
return nil
}
@ -353,14 +350,3 @@ func newTemplateNamespace(funcs map[string]any) *templateNamespace {
standaloneText: texttemplate.New("").Funcs(funcs),
}
}
func isText(t tpl.Template) bool {
switch t.(type) {
case *texttemplate.Template:
return true
case *htmltemplate.Template:
return false
default:
panic("unknown template type")
}
}

View file

@ -19,7 +19,6 @@ import (
"bytes"
"context"
"embed"
"errors"
"fmt"
"io"
"io/fs"
@ -114,18 +113,17 @@ func NewStore(opts StoreOptions, siteOpts SiteOptions) (*TemplateStore, error) {
panic("HTML output format not found")
}
s := &TemplateStore{
opts: opts,
siteOpts: siteOpts,
optsOrig: opts,
siteOptsOrig: siteOpts,
htmlFormat: html,
storeSite: configureSiteStorage(siteOpts, opts.Watching),
treeMain: doctree.NewSimpleTree[map[nodeKey]*TemplInfo](),
treeShortcodes: doctree.NewSimpleTree[map[string]map[TemplateDescriptor]*TemplInfo](),
templatesByPath: maps.NewCache[string, *TemplInfo](),
shortcodesByName: maps.NewCache[string, *TemplInfo](),
cacheLookupPartials: maps.NewCache[string, *TemplInfo](),
templatesSnapshotSet: maps.NewCache[*parse.Tree, struct{}](),
opts: opts,
siteOpts: siteOpts,
optsOrig: opts,
siteOptsOrig: siteOpts,
htmlFormat: html,
storeSite: configureSiteStorage(siteOpts, opts.Watching),
treeMain: doctree.NewSimpleTree[map[nodeKey]*TemplInfo](),
treeShortcodes: doctree.NewSimpleTree[map[string]map[TemplateDescriptor]*TemplInfo](),
templatesByPath: maps.NewCache[string, *TemplInfo](),
shortcodesByName: maps.NewCache[string, *TemplInfo](),
cacheLookupPartials: maps.NewCache[string, *TemplInfo](),
// Note that the funcs passed below is just for name validation.
tns: newTemplateNamespace(siteOpts.TemplateFuncs),
@ -144,10 +142,10 @@ func NewStore(opts StoreOptions, siteOpts SiteOptions) (*TemplateStore, error) {
if err := s.insertEmbedded(); err != nil {
return nil, err
}
if err := s.parseTemplates(false); err != nil {
if err := s.parseTemplates(); err != nil {
return nil, err
}
if err := s.extractInlinePartials(false); err != nil {
if err := s.extractInlinePartials(); err != nil {
return nil, err
}
if err := s.transformTemplates(); err != nil {
@ -425,11 +423,10 @@ type TemplateStore struct {
siteOpts SiteOptions
htmlFormat output.Format
treeMain *doctree.SimpleTree[map[nodeKey]*TemplInfo]
treeShortcodes *doctree.SimpleTree[map[string]map[TemplateDescriptor]*TemplInfo]
templatesByPath *maps.Cache[string, *TemplInfo]
shortcodesByName *maps.Cache[string, *TemplInfo]
templatesSnapshotSet *maps.Cache[*parse.Tree, struct{}]
treeMain *doctree.SimpleTree[map[nodeKey]*TemplInfo]
treeShortcodes *doctree.SimpleTree[map[string]map[TemplateDescriptor]*TemplInfo]
templatesByPath *maps.Cache[string, *TemplInfo]
shortcodesByName *maps.Cache[string, *TemplInfo]
dh descriptorHandler
@ -611,7 +608,7 @@ func (s *TemplateStore) LookupShortcodeByName(name string) *TemplInfo {
return ti
}
func (s *TemplateStore) LookupShortcode(q TemplateQuery) (*TemplInfo, error) {
func (s *TemplateStore) LookupShortcode(q TemplateQuery) *TemplInfo {
q.init()
k1 := s.key(q.Path)
@ -633,15 +630,13 @@ func (s *TemplateStore) LookupShortcode(q TemplateQuery) (*TemplInfo, error) {
}
for k, vv := range v {
best.candidates = append(best.candidates, vv)
if !q.Consider(vv) {
continue
}
weight := s.dh.compareDescriptors(q.Category, vv.subCategory == SubCategoryEmbedded, q.Desc, k)
weight.distance = distance
isBetter := best.isBetter(weight, vv)
if isBetter {
if best.isBetter(weight, vv) {
best.updateValues(weight, k2, k, vv)
}
}
@ -649,21 +644,8 @@ func (s *TemplateStore) LookupShortcode(q TemplateQuery) (*TemplInfo, error) {
return false, nil
})
if best.w.w1 <= 0 {
var err error
if s := best.candidatesAsStringSlice(); s != nil {
msg := fmt.Sprintf("no compatible template found for shortcode %q in %s", q.Name, s)
if !q.Desc.IsPlainText {
msg += "; note that to use plain text template shortcodes in HTML you need to use the shortcode {{% delimiter"
}
err = errors.New(msg)
} else {
err = fmt.Errorf("no template found for shortcode %q", q.Name)
}
return nil, err
}
return best.templ, nil
// Any match will do.
return best.templ
}
// PrintDebug is for testing/debugging only.
@ -711,16 +693,12 @@ func (s *TemplateStore) RefreshFiles(include func(fi hugofs.FileMetaInfo) bool)
if err := s.insertTemplates(include, true); err != nil {
return err
}
if err := s.createTemplatesSnapshot(); err != nil {
if err := s.parseTemplates(); err != nil {
return err
}
if err := s.parseTemplates(true); err != nil {
if err := s.extractInlinePartials(); err != nil {
return err
}
if err := s.extractInlinePartials(true); err != nil {
return err
}
if err := s.transformTemplates(); err != nil {
return err
}
@ -946,79 +924,61 @@ func (s *TemplateStore) extractIdentifiers(line string) []string {
return identifiers
}
func (s *TemplateStore) extractInlinePartials(rebuild bool) error {
func (s *TemplateStore) extractInlinePartials() error {
isPartialName := func(s string) bool {
return strings.HasPrefix(s, "partials/") || strings.HasPrefix(s, "_partials/")
}
p := s.tns
// We may find both inline and external partials in the current template namespaces,
// so only add the ones we have not seen before.
for templ := range s.allRawTemplates() {
if templ.Name() == "" || !isPartialName(templ.Name()) {
continue
addIfNotSeen := func(isText bool, templs ...tpl.Template) error {
for _, templ := range templs {
if templ.Name() == "" || !isPartialName(templ.Name()) {
continue
}
name := templ.Name()
if !paths.HasExt(name) {
// Assume HTML. This in line with how the lookup works.
name = name + s.htmlFormat.MediaType.FirstSuffix.FullSuffix
}
if !strings.HasPrefix(name, "_") {
name = "_" + name
}
pi := s.opts.PathParser.Parse(files.ComponentFolderLayouts, name)
ti, err := s.insertTemplate(pi, nil, false, s.treeMain)
if err != nil {
return err
}
if ti != nil {
ti.Template = templ
ti.noBaseOf = true
ti.subCategory = SubCategoryInline
ti.D.IsPlainText = isText
}
}
if rebuild && s.templatesSnapshotSet.Contains(getParseTree(templ)) {
// This partial was not created during this build.
continue
}
name := templ.Name()
if !paths.HasExt(name) {
// Assume HTML. This in line with how the lookup works.
name = name + s.htmlFormat.MediaType.FirstSuffix.FullSuffix
}
if !strings.HasPrefix(name, "_") {
name = "_" + name
}
pi := s.opts.PathParser.Parse(files.ComponentFolderLayouts, name)
ti, err := s.insertTemplate(pi, nil, SubCategoryInline, false, s.treeMain)
if err != nil {
return nil
}
addIfNotSeen(false, p.templatesIn(p.parseHTML)...)
addIfNotSeen(true, p.templatesIn(p.parseText)...)
for _, t := range p.baseofHtmlClones {
if err := addIfNotSeen(false, p.templatesIn(t)...); err != nil {
return err
}
if ti != nil {
ti.Template = templ
ti.noBaseOf = true
ti.subCategory = SubCategoryInline
ti.D.IsPlainText = isText(templ)
}
for _, t := range p.baseofTextClones {
if err := addIfNotSeen(true, p.templatesIn(t)...); err != nil {
return err
}
}
return nil
}
func (s *TemplateStore) allRawTemplates() iter.Seq[tpl.Template] {
p := s.tns
return func(yield func(tpl.Template) bool) {
for t := range p.templatesIn(p.parseHTML) {
if !yield(t) {
return
}
}
for t := range p.templatesIn(p.parseText) {
if !yield(t) {
return
}
}
for _, tt := range p.baseofHtmlClones {
for t := range p.templatesIn(tt) {
if !yield(t) {
return
}
}
}
for _, tt := range p.baseofTextClones {
for t := range p.templatesIn(tt) {
if !yield(t) {
return
}
}
}
}
}
func (s *TemplateStore) insertEmbedded() error {
return fs.WalkDir(embeddedTemplatesFs, ".", func(tpath string, d fs.DirEntry, err error) error {
return fs.WalkDir(embeddedTemplatesFs, ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
@ -1026,7 +986,7 @@ func (s *TemplateStore) insertEmbedded() error {
return nil
}
templb, err := embeddedTemplatesFs.ReadFile(tpath)
templb, err := embeddedTemplatesFs.ReadFile(path)
if err != nil {
return err
}
@ -1034,7 +994,7 @@ func (s *TemplateStore) insertEmbedded() error {
// Get the newlines on Windows in line with how we had it back when we used Go Generate
// to write the templates to Go files.
templ := string(bytes.ReplaceAll(templb, []byte("\r\n"), []byte("\n")))
name := strings.TrimPrefix(filepath.ToSlash(tpath), "embedded/templates/")
name := strings.TrimPrefix(filepath.ToSlash(path), "embedded/templates/")
insertOne := func(name, content string) error {
pi := s.opts.PathParser.Parse(files.ComponentFolderLayouts, name)
@ -1048,7 +1008,7 @@ func (s *TemplateStore) insertEmbedded() error {
return err
}
} else {
ti, err = s.insertTemplate(pi, nil, SubCategoryEmbedded, false, s.treeMain)
ti, err = s.insertTemplate(pi, nil, false, s.treeMain)
if err != nil {
return err
}
@ -1064,19 +1024,6 @@ func (s *TemplateStore) insertEmbedded() error {
return nil
}
// Copy the embedded HTML table render hook to each output format.
// See https://github.com/gohugoio/hugo/issues/13351.
if name == path.Join(containerMarkup, "render-table.html") {
for _, of := range s.opts.OutputFormats {
path := paths.TrimExt(name) + "." + of.Name + of.MediaType.FirstSuffix.FullSuffix
if err := insertOne(path, templ); err != nil {
return err
}
}
return nil
}
if err := insertOne(name, templ); err != nil {
return err
}
@ -1142,7 +1089,7 @@ func (s *TemplateStore) insertShortcode(pi *paths.Path, fi hugofs.FileMetaInfo,
return ti, nil
}
func (s *TemplateStore) insertTemplate(pi *paths.Path, fi hugofs.FileMetaInfo, subCategory SubCategory, replace bool, tree doctree.Tree[map[nodeKey]*TemplInfo]) (*TemplInfo, error) {
func (s *TemplateStore) insertTemplate(pi *paths.Path, fi hugofs.FileMetaInfo, replace bool, tree doctree.Tree[map[nodeKey]*TemplInfo]) (*TemplInfo, error) {
key, _, category, d, err := s.toKeyCategoryAndDescriptor(pi)
// See #13577. Warn for now.
if err != nil {
@ -1156,7 +1103,7 @@ func (s *TemplateStore) insertTemplate(pi *paths.Path, fi hugofs.FileMetaInfo, s
return nil, nil
}
return s.insertTemplate2(pi, fi, key, category, subCategory, d, replace, false, tree)
return s.insertTemplate2(pi, fi, key, category, d, replace, false, tree)
}
func (s *TemplateStore) insertTemplate2(
@ -1164,7 +1111,6 @@ func (s *TemplateStore) insertTemplate2(
fi hugofs.FileMetaInfo,
key string,
category Category,
subCategory SubCategory,
d TemplateDescriptor,
replace, isLegacyMapped bool,
tree doctree.Tree[map[nodeKey]*TemplInfo],
@ -1187,26 +1133,12 @@ func (s *TemplateStore) insertTemplate2(
tree.Insert(key, m)
}
nkExisting, existingFound := m[nk]
if !replace && existingFound && fi != nil && nkExisting.Fi != nil {
// See issue #13715.
// We do the merge on the file system level, but from Hugo v0.146.0 we have a situation where
// the project may well have a different layouts layout compared to the theme(s) it uses.
// We could possibly have fixed that on a lower (file system) level, but since this is just
// a temporary situation (until all projects are updated),
// do a replace here if the file comes from higher up in the module chain.
replace = fi.Meta().ModuleOrdinal < nkExisting.Fi.Meta().ModuleOrdinal
}
if !replace && existingFound {
// Always replace inline partials to allow for reloading.
replace = subCategory == SubCategoryInline && nkExisting.subCategory == SubCategoryInline
}
if !replace && existingFound {
if len(pi.Identifiers()) >= len(nkExisting.PathInfo.Identifiers()) {
// e.g. /pages/home.foo.html and /pages/home.html where foo may be a valid language name in another site.
return nil, nil
if !replace {
if v, found := m[nk]; found {
if len(pi.Identifiers()) >= len(v.PathInfo.Identifiers()) {
// e.g. /pages/home.foo.html and /pages/home.html where foo may be a valid language name in another site.
return nil, nil
}
}
}
@ -1233,7 +1165,7 @@ func (s *TemplateStore) insertTemplate2(
return ti, nil
}
func (s *TemplateStore) insertTemplates(include func(fi hugofs.FileMetaInfo) bool, partialRebuild bool) error {
func (s *TemplateStore) insertTemplates(include func(fi hugofs.FileMetaInfo) bool, replace bool) error {
if include == nil {
include = func(fi hugofs.FileMetaInfo) bool {
return true
@ -1415,7 +1347,7 @@ func (s *TemplateStore) insertTemplates(include func(fi hugofs.FileMetaInfo) boo
}
if partialRebuild && pi.NameNoIdentifier() == baseNameBaseof {
if replace && pi.NameNoIdentifier() == baseNameBaseof {
// A baseof file has changed.
resetBaseVariants = true
}
@ -1423,12 +1355,12 @@ func (s *TemplateStore) insertTemplates(include func(fi hugofs.FileMetaInfo) boo
var ti *TemplInfo
var err error
if pi.Type() == paths.TypeShortcode {
ti, err = s.insertShortcode(pi, fi, partialRebuild, s.treeShortcodes)
ti, err = s.insertShortcode(pi, fi, replace, s.treeShortcodes)
if err != nil || ti == nil {
return err
}
} else {
ti, err = s.insertTemplate(pi, fi, SubCategoryMain, partialRebuild, s.treeMain)
ti, err = s.insertTemplate(pi, fi, replace, s.treeMain)
if err != nil || ti == nil {
return err
}
@ -1462,7 +1394,7 @@ func (s *TemplateStore) insertTemplates(include func(fi hugofs.FileMetaInfo) boo
desc.IsPlainText = outputFormat.IsPlainText
desc.MediaType = mediaType.Type
ti, err := s.insertTemplate2(pi, fi, targetPath, category, SubCategoryMain, desc, true, true, s.treeMain)
ti, err := s.insertTemplate2(pi, fi, targetPath, category, desc, true, true, s.treeMain)
if err != nil {
return err
}
@ -1473,7 +1405,6 @@ func (s *TemplateStore) insertTemplates(include func(fi hugofs.FileMetaInfo) boo
if err := s.tns.readTemplateInto(ti); err != nil {
return err
}
}
if resetBaseVariants {
@ -1500,15 +1431,7 @@ func (s *TemplateStore) key(dir string) string {
return paths.TrimTrailing(dir)
}
func (s *TemplateStore) createTemplatesSnapshot() error {
s.templatesSnapshotSet.Reset()
for t := range s.allRawTemplates() {
s.templatesSnapshotSet.Set(getParseTree(t), struct{}{})
}
return nil
}
func (s *TemplateStore) parseTemplates(replace bool) error {
func (s *TemplateStore) parseTemplates() error {
if err := func() error {
// Read and parse all templates.
for _, v := range s.treeMain.All() {
@ -1516,7 +1439,7 @@ func (s *TemplateStore) parseTemplates(replace bool) error {
if vv.state == processingStateTransformed {
continue
}
if err := s.parseTemplate(vv, replace); err != nil {
if err := s.parseTemplate(vv); err != nil {
return err
}
}
@ -1536,7 +1459,7 @@ func (s *TemplateStore) parseTemplates(replace bool) error {
// The regular expression used to detect if a template needs a base template has some
// rare false positives. Assume we don't need one.
vv.noBaseOf = true
if err := s.parseTemplate(vv, replace); err != nil {
if err := s.parseTemplate(vv); err != nil {
return err
}
continue
@ -1565,7 +1488,7 @@ func (s *TemplateStore) parseTemplates(replace bool) error {
if vvv.state == processingStateTransformed {
continue
}
if err := s.parseTemplate(vvv, replace); err != nil {
if err := s.parseTemplate(vvv); err != nil {
return err
}
}
@ -1885,11 +1808,10 @@ type TextTemplatHandler interface {
}
type bestMatch struct {
templ *TemplInfo
desc TemplateDescriptor
w weight
key string
candidates []*TemplInfo
templ *TemplInfo
desc TemplateDescriptor
w weight
key string
// settings.
defaultOutputformat string
@ -1900,18 +1822,6 @@ func (best *bestMatch) reset() {
best.w = weight{}
best.desc = TemplateDescriptor{}
best.key = ""
best.candidates = nil
}
func (best *bestMatch) candidatesAsStringSlice() []string {
if len(best.candidates) == 0 {
return nil
}
candidates := make([]string, len(best.candidates))
for i, v := range best.candidates {
candidates[i] = v.PathInfo.Path()
}
return candidates
}
func (best *bestMatch) isBetter(w weight, ti *TemplInfo) bool {
@ -1921,6 +1831,7 @@ func (best *bestMatch) isBetter(w weight, ti *TemplInfo) bool {
}
if w.w1 <= 0 {
if best.w.w1 <= 0 {
return ti.PathInfo.Path() < best.templ.PathInfo.Path()
}

View file

@ -920,26 +920,6 @@ func TestPartialHTML(t *testing.T) {
b.AssertFileContent("public/index.html", "<link rel=\"stylesheet\" href=\"/css/style.css\">")
}
func TestPartialPlainTextInHTML(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
-- layouts/all.html --
<html>
<head>
{{ partial "mypartial.txt" . }}
</head>
</html>
-- layouts/partials/mypartial.txt --
My <div>partial</div>.
`
b := hugolib.Test(t, files)
b.AssertFileContent("public/index.html", "My &lt;div&gt;partial&lt;/div&gt;.")
}
// Issue #13593.
func TestGoatAndNoGoat(t *testing.T) {
t.Parallel()
@ -1123,35 +1103,6 @@ All.
b.AssertLogContains("unrecognized render hook")
}
func TestLayoutNotFound(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
-- layouts/single.html --
Single.
`
b := hugolib.Test(t, files, hugolib.TestOptWarn())
b.AssertLogContains("WARN found no layout file for \"html\" for kind \"home\"")
}
func TestLayoutOverrideThemeWhenThemeOnOldFormatIssue13715(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
theme = "mytheme"
-- layouts/list.html --
layouts/list.html
-- themes/mytheme/layouts/_default/list.html --
mytheme/layouts/_default/list.html
`
b := hugolib.Test(t, files)
b.AssertFileContent("public/index.html", "layouts/list.html")
}
func BenchmarkExecuteWithContext(b *testing.B) {
files := `
-- hugo.toml --
@ -1246,8 +1197,8 @@ s2.
Category: tplimpl.CategoryShortcode,
Desc: desc,
}
v, err := store.LookupShortcode(q)
if v == nil || err != nil {
v := store.LookupShortcode(q)
if v == nil {
b.Fatal("not found")
}
}
@ -1508,43 +1459,3 @@ mytexts|safeHTML: {{ partial "mytext.txt" . | safeHTML }}
"mytexts|safeHTML: <div>mytext</div>",
)
}
func TestIssue13351(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['page','rss','section','sitemap','taxonomy','term']
[outputs]
home = ['html','json']
[outputFormats.html]
weight = 1
[outputFormats.json]
weight = 2
-- content/_index.md --
---
title: home
---
a|b
:--|:--
1|2
-- layouts/index.html --
{{ .Content }}
-- layouts/index.json --
{{ .Content }}
`
b := hugolib.Test(t, files)
b.AssertFileContent("public/index.html", "<table>")
b.AssertFileContent("public/index.json", "<table>")
f := strings.ReplaceAll(files, "weight = 1", "weight = 0")
b = hugolib.Test(t, f)
b.AssertFileContent("public/index.html", "<table>")
b.AssertFileContent("public/index.json", "<table>")
f = strings.ReplaceAll(files, "weight = 1", "")
b = hugolib.Test(t, f)
b.AssertFileContent("public/index.html", "<table>")
b.AssertFileContent("public/index.json", "<table>")
}

View file

@ -17,10 +17,8 @@ package transform
import (
"bytes"
"context"
"encoding/json"
"encoding/xml"
"errors"
"fmt"
"html"
"html/template"
"io"
@ -236,7 +234,6 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, er
MinRuleThickness: 0.04,
ErrorColor: "#cc0000",
ThrowOnError: true,
Strict: "error",
},
}
@ -246,23 +243,8 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, er
}
}
switch katexInput.Options.Strict {
case "error", "ignore", "warn":
// Valid strict mode, continue
default:
return "", fmt.Errorf("invalid strict mode; expected one of error, ignore, or warn; received %s", katexInput.Options.Strict)
}
type fileCacheEntry struct {
Version string `json:"version"`
Output string `json:"output"`
Warnings []string `json:"warnings,omitempty"`
}
const fileCacheEntryVersion = "v1" // Increment on incompatible changes.
s := hashing.HashString(args...)
key := "tomath/" + fileCacheEntryVersion + "/" + s[:2] + "/" + s[2:]
key := "tomath/" + s[:2] + "/" + s[2:]
fileCache := ns.deps.ResourceSpec.FileCaches.MiscCache()
v, err := ns.cacheMath.GetOrCreate(key, func(string) (template.HTML, error) {
@ -283,35 +265,15 @@ func (ns *Namespace) ToMath(ctx context.Context, args ...any) (template.HTML, er
if err != nil {
return nil, err
}
e := fileCacheEntry{
Version: fileCacheEntryVersion,
Output: result.Data.Output,
Warnings: result.Header.Warnings,
}
buf := &bytes.Buffer{}
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
if err := enc.Encode(e); err != nil {
return nil, fmt.Errorf("failed to encode file cache entry: %w", err)
}
return hugio.NewReadSeekerNoOpCloserFromBytes(buf.Bytes()), nil
return hugio.NewReadSeekerNoOpCloserFromString(result.Data.Output), nil
})
if err != nil {
return "", err
}
var e fileCacheEntry
if err := json.NewDecoder(r).Decode(&e); err != nil {
return "", fmt.Errorf("failed to decode file cache entry: %w", err)
}
s, err := hugio.ReadString(r)
for _, warning := range e.Warnings {
ns.deps.Log.Warnf("transform.ToMath: %s", warning)
}
return template.HTML(e.Output), err
return template.HTML(s), err
})
if err != nil {
return "", err

View file

@ -495,43 +495,3 @@ DATA
}
}
}
// Issue 13729
func TestToMathStrictMode(t *testing.T) {
t.Parallel()
files := `
-- hugo.toml --
disableKinds = ['page','rss','section','sitemap','taxonomy','term']
-- layouts/all.html --
{{ transform.ToMath "a %" dict }}
-- foo --
`
// strict mode: default
f := strings.ReplaceAll(files, "dict", "")
b, err := hugolib.TestE(t, f)
b.Assert(err.Error(), qt.Contains, "[commentAtEnd]")
// strict mode: error
f = strings.ReplaceAll(files, "dict", `(dict "strict" "error")`)
b, err = hugolib.TestE(t, f)
b.Assert(err.Error(), qt.Contains, "[commentAtEnd]")
// strict mode: ignore
f = strings.ReplaceAll(files, "dict", `(dict "strict" "ignore")`)
b = hugolib.Test(t, f, hugolib.TestOptWarn())
b.AssertLogMatches("")
b.AssertFileContent("public/index.html", `<annotation encoding="application/x-tex">a %</annotation>`)
// strict: warn
f = strings.ReplaceAll(files, "dict", `(dict "strict" "warn")`)
b = hugolib.Test(t, f, hugolib.TestOptWarn())
b.AssertLogMatches("[commentAtEnd]")
b.AssertFileContent("public/index.html", `<annotation encoding="application/x-tex">a %</annotation>`)
// strict mode: invalid value
f = strings.ReplaceAll(files, "dict", `(dict "strict" "foo")`)
b, err = hugolib.TestE(t, f)
b.Assert(err.Error(), qt.Contains, "invalid strict mode")
}