Move common/hugo/HugoInfo to resources/page

* This break the circular dependency between hugolib and resources/page, and allow HugoInfo to use the proper Page ans Site interfaces.
* It's a little misplaced, but it makes everything easier to maintain and test, so that's well worth it.
This commit is contained in:
Bjørn Erik Pedersen
2026-02-16 20:09:37 +01:00
parent 3f9d0ad2b6
commit 3c823408ee
15 changed files with 274 additions and 251 deletions
+1 -1
View File
@@ -246,7 +246,7 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, net.Listener, string
logger := f.c.r.logger
if i == 0 {
r.Printf("Environment: %q\n", f.c.hugoTry().Deps.Site.Hugo().Environment)
r.Printf("Environment: %q\n", f.c.hugoTry().Deps.Site.Hugo().Environment())
mainTarget := "disk"
if f.c.r.renderToMemory {
mainTarget = "memory"
+16 -142
View File
@@ -16,7 +16,6 @@ package hugo
import (
"context"
"fmt"
"html/template"
"os"
"path/filepath"
"runtime/debug"
@@ -25,17 +24,16 @@ import (
"sync"
"time"
"github.com/bep/helpers/contexthelpers"
"github.com/bep/logg"
"github.com/bep/godartsass/v2"
"github.com/gohugoio/hugo/common/hexec"
"github.com/gohugoio/hugo/common/hstore"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/version"
"github.com/gohugoio/hugo/hugofs/files"
"github.com/bep/helpers/contexthelpers"
"github.com/spf13/afero"
iofs "io/fs"
@@ -56,99 +54,24 @@ var (
vendorInfo string
)
var _ hstore.StoreProvider = (*HugoInfo)(nil)
// HugoInfo contains information about the current Hugo environment
type HugoInfo struct {
CommitHash string
BuildDate string
// The build environment.
// Defaults are "production" (hugo) and "development" (hugo server).
// This can also be set by the user.
// It can be any string, but it will be all lower case.
Environment string
// version of go that the Hugo binary was built with
GoVersion string
conf ConfigProvider
deps []*Dependency
sitesProvider SitesProvider
store *hstore.Scratch
// Context gives access to some of the context scoped variables.
Context Context
// BuildInfo holds build information extracted from runtime/debug.
type BuildInfo struct {
Revision string
RevisionTime string
GoVersion string
}
// Version returns the current version as a comparable version string.
func (i HugoInfo) Version() version.VersionString {
return CurrentVersion.Version()
}
// Generator a Hugo meta generator HTML tag.
func (i HugoInfo) Generator() template.HTML {
return template.HTML(fmt.Sprintf(`<meta name="generator" content="Hugo %s">`, CurrentVersion.String()))
}
// IsDevelopment reports whether the current running environment is "development".
func (i HugoInfo) IsDevelopment() bool {
return i.Environment == EnvironmentDevelopment
}
// IsProduction reports whether the current running environment is "production".
func (i HugoInfo) IsProduction() bool {
return i.Environment == EnvironmentProduction
}
// IsServer reports whether the built-in server is running.
func (i HugoInfo) IsServer() bool {
return i.conf.Running()
}
// IsExtended reports whether the Hugo binary is the extended version.
func (i HugoInfo) IsExtended() bool {
return IsExtended
}
// WorkingDir returns the project working directory.
func (i HugoInfo) WorkingDir() string {
return i.conf.WorkingDir()
}
// Deps gets a list of dependencies for this Hugo build.
func (i HugoInfo) Deps() []*Dependency {
return i.deps
}
func (i HugoInfo) Store() *hstore.Scratch {
return i.store
}
// Deprecated: Use hugo.IsMultihost instead.
func (i HugoInfo) IsMultiHost() bool {
Deprecate("hugo.IsMultiHost", "Use hugo.IsMultihost instead.", "v0.124.0")
return i.conf.IsMultihost()
}
// IsMultihost reports whether each configured language has a unique baseURL.
func (i HugoInfo) IsMultihost() bool {
return i.conf.IsMultihost()
}
// IsMultilingual reports whether there are two or more configured languages.
func (i HugoInfo) IsMultilingual() bool {
return i.conf.IsMultilingual()
}
// Sites returns all sites for all dimensions.
func (i HugoInfo) Sites() any {
if i.sitesProvider == nil {
// GetBuildInfo returns the build info for the current binary.
func GetBuildInfo() *BuildInfo {
bi := getBuildInfo()
if bi == nil {
return nil
}
return i.sitesProvider.Sites()
return &BuildInfo{
Revision: bi.Revision,
RevisionTime: bi.RevisionTime,
GoVersion: bi.GoVersion,
}
}
type contextKey uint8
@@ -159,6 +82,7 @@ const (
var markupScope = contexthelpers.NewContextDispatcher[string](contextKeyMarkupScope)
// Context gives access to some of the context scoped variables.
type Context struct{}
func (c Context) MarkupScope(ctx context.Context) string {
@@ -175,56 +99,6 @@ func GetMarkupScope(ctx context.Context) string {
return markupScope.Get(ctx)
}
// ConfigProvider represents the config options that are relevant for HugoInfo.
type ConfigProvider interface {
Environment() string
Running() bool
WorkingDir() string
IsMultihost() bool
IsMultilingual() bool
}
// SitesProvider provides access to all sites.
type SitesProvider interface {
Sites() any
}
// HugoInfoOptions defines the providers required to initialize HugoInfo.
type HugoInfoOptions struct {
Conf ConfigProvider
SitesProvider SitesProvider
}
// NewInfo creates a new Hugo Info object.
func NewInfo(opts HugoInfoOptions, deps []*Dependency) HugoInfo {
if opts.Conf.Environment() == "" {
panic("environment not set")
}
var (
commitHash string
buildDate string
goVersion string
)
bi := getBuildInfo()
if bi != nil {
commitHash = bi.Revision
buildDate = bi.RevisionTime
goVersion = bi.GoVersion
}
return HugoInfo{
CommitHash: commitHash,
BuildDate: buildDate,
Environment: opts.Conf.Environment(),
conf: opts.Conf,
deps: deps,
sitesProvider: opts.SitesProvider,
store: hstore.NewScratch(),
GoVersion: goVersion,
}
}
// GetExecEnviron creates and gets the common os/exec environment used in the
// external programs we interact with via os/exec, e.g. postcss.
func GetExecEnviron(workDir string, cfg config.AllProvider, fs afero.Fs) []string {
+10 -69
View File
@@ -15,49 +15,12 @@ package hugo
import (
"context"
"fmt"
"testing"
"github.com/bep/logg"
qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/common/version"
)
func TestHugoInfo(t *testing.T) {
c := qt.New(t)
opts := HugoInfoOptions{
Conf: testConfig{environment: "production", workingDir: "/mywork", running: false},
}
hugoInfo := NewInfo(opts, nil)
c.Assert(hugoInfo.Version(), qt.Equals, CurrentVersion.Version())
c.Assert(fmt.Sprintf("%T", version.VersionString("")), qt.Equals, fmt.Sprintf("%T", hugoInfo.Version()))
c.Assert(hugoInfo.WorkingDir(), qt.Equals, "/mywork")
bi := getBuildInfo()
if bi != nil {
c.Assert(hugoInfo.CommitHash, qt.Equals, bi.Revision)
c.Assert(hugoInfo.BuildDate, qt.Equals, bi.RevisionTime)
c.Assert(hugoInfo.GoVersion, qt.Equals, bi.GoVersion)
}
c.Assert(hugoInfo.Environment, qt.Equals, "production")
c.Assert(string(hugoInfo.Generator()), qt.Contains, fmt.Sprintf("Hugo %s", hugoInfo.Version()))
c.Assert(hugoInfo.IsDevelopment(), qt.Equals, false)
c.Assert(hugoInfo.IsProduction(), qt.Equals, true)
c.Assert(hugoInfo.IsExtended(), qt.Equals, IsExtended)
c.Assert(hugoInfo.IsServer(), qt.Equals, false)
opts = HugoInfoOptions{
Conf: testConfig{environment: "development", running: true},
}
devHugoInfo := NewInfo(opts, nil)
c.Assert(devHugoInfo.IsDevelopment(), qt.Equals, true)
c.Assert(devHugoInfo.IsProduction(), qt.Equals, false)
c.Assert(devHugoInfo.IsServer(), qt.Equals, true)
}
func TestDeprecationLogLevelFromVersion(t *testing.T) {
c := qt.New(t)
@@ -79,42 +42,20 @@ func TestDeprecationLogLevelFromVersion(t *testing.T) {
func TestMarkupScope(t *testing.T) {
c := qt.New(t)
opts := HugoInfoOptions{
Conf: testConfig{environment: "production", workingDir: "/mywork", running: false},
}
info := NewInfo(opts, nil)
ctx := context.Background()
ctx = SetMarkupScope(ctx, "foo")
c.Assert(info.Context.MarkupScope(ctx), qt.Equals, "foo")
var hugoCtx Context
c.Assert(hugoCtx.MarkupScope(ctx), qt.Equals, "foo")
c.Assert(GetMarkupScope(ctx), qt.Equals, "foo")
}
type testConfig struct {
environment string
running bool
workingDir string
multihost bool
multilingual bool
}
func TestGetBuildInfo(t *testing.T) {
c := qt.New(t)
func (c testConfig) Environment() string {
return c.environment
}
func (c testConfig) Running() bool {
return c.running
}
func (c testConfig) WorkingDir() string {
return c.workingDir
}
func (c testConfig) IsMultihost() bool {
return c.multihost
}
func (c testConfig) IsMultilingual() bool {
return c.multilingual
bi := GetBuildInfo()
// In test mode, build info may or may not be available.
if bi != nil {
c.Assert(bi.GoVersion, qt.Not(qt.Equals), "")
}
}
+8 -6
View File
@@ -19,7 +19,6 @@ import (
"fmt"
"io"
"iter"
"slices"
"strings"
"sync"
"sync/atomic"
@@ -42,7 +41,6 @@ import (
"github.com/gohugoio/hugo/common/hmaps"
"github.com/gohugoio/hugo/common/hsync"
"github.com/gohugoio/hugo/common/htime"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/common/para"
"github.com/gohugoio/hugo/common/terminal"
@@ -71,7 +69,7 @@ type HugoSites struct {
Configs *allconfig.Configs
hugoInfo hugo.HugoInfo
hugoInfo page.HugoInfo
// Render output formats for all sites.
renderFormats output.Formats
@@ -124,14 +122,18 @@ type HugoSites struct {
buildCounter atomic.Uint64
}
// hugoSitesSitesProvider is a wrapper that implements hugo.SitesProvider.
// hugoSitesSitesProvider is a wrapper that implements page.SitesProvider.
// This avoids naming conflict with HugoSites.Sites field.
type hugoSitesSitesProvider struct {
h *HugoSites
}
func (sp hugoSitesSitesProvider) Sites() any {
return slices.Collect(sp.h.allSites(nil))
func (sp hugoSitesSitesProvider) Sites() page.Sites {
sites := make(page.Sites, 0)
for s := range sp.h.allSites(nil) {
sites = append(sites, s.Site())
}
return sites
}
type progressReporter struct {
+1
View File
@@ -607,6 +607,7 @@ func (ps *pageState) initCommonProviders(pp pagePaths) error {
ps.targetPathDescriptor = pp.targetPathDescriptor
ps.RefProvider = newPageRef(ps)
ps.SitesProvider = ps.s
ps.SiteProvider = ps
return nil
}
+1
View File
@@ -66,6 +66,7 @@ type pageCommon struct {
page.RawContentProvider
page.RefProvider
page.ShortcodeInfoProvider
page.SiteProvider
page.SitesProvider
page.TranslationsProvider
page.TreeProvider
+11 -9
View File
@@ -520,11 +520,19 @@ func newHugoSites(
// Create a sites provider that avoids naming conflict with HugoSites.Sites field.
sp := hugoSitesSitesProvider{h: h}
opts := hugo.HugoInfoOptions{
opts := page.HugoInfoOptions{
Conf: h.Configs.GetFirstLanguageConfig(),
SitesProvider: sp,
Deps: dependencies,
}
h.hugoInfo = hugo.NewInfo(opts, dependencies)
if bi := hugo.GetBuildInfo(); bi != nil {
opts.CommitHash = bi.Revision
opts.BuildDate = bi.RevisionTime
opts.GoVersion = bi.GoVersion
}
h.hugoInfo = page.NewHugoInfo(opts)
var prototype *deps.Deps
@@ -668,13 +676,7 @@ func (s *Site) MainSections() []string {
}
// Returns a struct with some information about the build.
func (s *Site) Hugo() hugo.HugoInfo {
if s.h == nil {
panic("site: hugo: h not initialized")
}
if s.h.hugoInfo.Environment == "" {
panic("site: hugo: hugoInfo not initialized")
}
func (s *Site) Hugo() page.HugoInfo {
return s.h.hugoInfo
}
+158
View File
@@ -0,0 +1,158 @@
// Copyright 2026 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package page
import (
"fmt"
"html/template"
"github.com/gohugoio/hugo/common/hstore"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/version"
)
var _ hstore.StoreProvider = (*HugoInfo)(nil)
type hugoInfoProviders struct {
SitesProvider
}
// HugoInfo contains information about the current Hugo environment.
type HugoInfo struct {
CommitHash string
BuildDate string
// Version of Go that the Hugo binary was built with.
GoVersion string
// Avoid exporting the embedded providers directly, as they may be used by the template layer.
hugoInfoProviders
// Context gives access to some of the context scoped variables.
Context hugo.Context
opts HugoInfoOptions
store *hstore.Scratch
}
// Version returns the current version as a comparable version string.
func (i HugoInfo) Version() version.VersionString {
return hugo.CurrentVersion.Version()
}
// Generator returns a Hugo meta generator HTML tag.
func (i HugoInfo) Generator() template.HTML {
return template.HTML(fmt.Sprintf(`<meta name="generator" content="Hugo %s">`, hugo.CurrentVersion.String()))
}
// Environment returns the build environment.
// Defaults are "production" (hugo) and "development" (hugo server).
// This can also be set by the user.
// It can be any string, but it will be all lower case.
func (i HugoInfo) Environment() string {
return i.opts.Conf.Environment()
}
// IsDevelopment reports whether the current running environment is "development".
func (i HugoInfo) IsDevelopment() bool {
return i.Environment() == hugo.EnvironmentDevelopment
}
// IsProduction reports whether the current running environment is "production".
func (i HugoInfo) IsProduction() bool {
return i.Environment() == hugo.EnvironmentProduction
}
// IsServer reports whether the built-in server is running.
func (i HugoInfo) IsServer() bool {
return i.opts.Conf.Running()
}
// IsExtended reports whether the Hugo binary is the extended version.
func (i HugoInfo) IsExtended() bool {
return hugo.IsExtended
}
// WorkingDir returns the project working directory.
func (i HugoInfo) WorkingDir() string {
return i.opts.Conf.WorkingDir()
}
// Deps gets a list of dependencies for this Hugo build.
func (i HugoInfo) Deps() []*hugo.Dependency {
return i.opts.Deps
}
func (i HugoInfo) Store() *hstore.Scratch {
return i.store
}
// Deprecated: Use hugo.IsMultihost instead.
func (i HugoInfo) IsMultiHost() bool {
hugo.Deprecate("hugo.IsMultiHost", "Use hugo.IsMultihost instead.", "v0.124.0")
return i.opts.Conf.IsMultihost()
}
// IsMultihost reports whether each configured language has a unique baseURL.
func (i HugoInfo) IsMultihost() bool {
return i.opts.Conf.IsMultihost()
}
// IsMultilingual reports whether there are two or more configured languages.
func (i HugoInfo) IsMultilingual() bool {
return i.opts.Conf.IsMultilingual()
}
// HugoInfoConfigProvider represents the config options that are relevant for HugoInfo.
type HugoInfoConfigProvider interface {
Environment() string
Running() bool
WorkingDir() string
IsMultihost() bool
IsMultilingual() bool
}
// HugoInfoOptions defines the providers required to initialize HugoInfo.
type HugoInfoOptions struct {
Conf HugoInfoConfigProvider
Deps []*hugo.Dependency
SitesProvider SitesProvider
CommitHash string
BuildDate string
GoVersion string
}
// NewHugoInfo creates a new Hugo Info object.
func NewHugoInfo(opts HugoInfoOptions) HugoInfo {
if opts.Conf == nil {
panic("config provider not set")
}
if opts.Conf.Environment() == "" {
panic("environment not set")
}
if opts.SitesProvider == nil {
opts.SitesProvider = nopSitesProvider{}
}
return HugoInfo{
CommitHash: opts.CommitHash,
BuildDate: opts.BuildDate,
GoVersion: opts.GoVersion,
hugoInfoProviders: hugoInfoProviders{SitesProvider: opts.SitesProvider},
opts: opts,
store: hstore.NewScratch(),
}
}
+35
View File
@@ -0,0 +1,35 @@
// Copyright 2026 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package page
import (
"testing"
qt "github.com/frankban/quicktest"
)
func TestNewHugoInfo(t *testing.T) {
c := qt.New(t)
c.Assert(func() { NewHugoInfo(HugoInfoOptions{}) }, qt.PanicMatches, "config provider not set")
opts := HugoInfoOptions{
Conf: testConfig{environment: "development"},
}
h := NewHugoInfo(opts)
c.Assert(h.Environment(), qt.Equals, "development")
c.Assert(h.Sites(), qt.IsNil)
}
+13 -3
View File
@@ -374,6 +374,7 @@ type PageWithoutContent interface {
resource.TranslationKeyProvider
TranslationsProvider
SiteProvider
SitesProvider
// Helper methods
@@ -453,14 +454,23 @@ type ShortcodeInfoProvider interface {
HasShortcode(name string) bool
}
type nopSitesProvider struct{}
func (nopSitesProvider) Sites() Sites {
return nil
}
// SitesProvider provide accessors to get sites.
type SitesProvider interface {
// Site returns the current site.
Site() Site
// Sites returns all sites.
// Sites returns all sites for all dimensions.
Sites() Sites
}
// SiteProvider provides access to the current site.
type SiteProvider interface {
Site() Site
}
// TableOfContentsProvider provides the table of contents for a Page.
type TableOfContentsProvider interface {
// TableOfContents returns the table of contents for the page rendered as HTML.
+1 -1
View File
@@ -61,7 +61,7 @@ type PageMatcher struct {
}
func (m PageMatcher) Matches(p Page) bool {
return m.Match(p.Kind(), p.Path(), p.Site().Hugo().Environment, nil)
return m.Match(p.Kind(), p.Path(), p.Site().Hugo().Environment(), nil)
}
func (m PageMatcher) Match(kind, path, environment string, sitesMatrix sitesmatrix.VectorProvider) bool {
+6 -7
View File
@@ -18,7 +18,6 @@ import (
"testing"
"github.com/gohugoio/hugo/common/hmaps"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/hugolib/sitesmatrix"
@@ -28,21 +27,21 @@ import (
func TestPageMatcher(t *testing.T) {
c := qt.New(t)
opts := hugo.HugoInfoOptions{
opts := HugoInfoOptions{
Conf: testConfig{environment: "development"},
}
developmentTestSite := testSite{h: hugo.NewInfo(opts, nil)}
developmentTestSite := &testSite{h: NewHugoInfo(opts)}
opts = hugo.HugoInfoOptions{
opts = HugoInfoOptions{
Conf: testConfig{environment: "production"},
}
productionTestSite := testSite{h: hugo.NewInfo(opts, nil)}
productionTestSite := &testSite{h: NewHugoInfo(opts)}
dec := cascadeConfigDecoder{}
p1, p2, p3 := &testPage{path: "/p1", kind: "section", lang: "en", site: developmentTestSite},
&testPage{path: "p2", kind: "page", lang: "no", site: productionTestSite},
&testPage{path: "p3", kind: "page", lang: "en"}
&testPage{path: "p3", kind: "page", lang: "en", site: developmentTestSite}
c.Run("Matches", func(c *qt.C) {
m := PageMatcher{Kind: "section"}
@@ -68,7 +67,7 @@ func TestPageMatcher(t *testing.T) {
m = PageMatcher{Environment: "development"}
c.Assert(m.Matches(p1), qt.Equals, true)
c.Assert(m.Matches(p2), qt.Equals, false)
c.Assert(m.Matches(p3), qt.Equals, false)
c.Assert(m.Matches(p3), qt.Equals, true)
m = PageMatcher{Environment: "production"}
c.Assert(m.Matches(p1), qt.Equals, false)
+1 -2
View File
@@ -31,7 +31,6 @@ import (
"github.com/gohugoio/hugo/common/hmaps"
"github.com/gohugoio/hugo/common/hstore"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/source"
@@ -196,7 +195,7 @@ func (p *nopPage) HasShortcode(name string) bool {
return false
}
func (p *nopPage) Hugo() (h hugo.HugoInfo) {
func (p *nopPage) Hugo() (h HugoInfo) {
return
}
+6 -7
View File
@@ -26,7 +26,6 @@ import (
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/navigation"
)
@@ -87,7 +86,7 @@ type Site interface {
IsDefault() bool
// Returns a struct with some information about the build.
Hugo() hugo.HugoInfo
Hugo() HugoInfo
// Returns the BaseURL for this Site.
BaseURL() string
@@ -251,7 +250,7 @@ func (s *siteWrapper) Config() SiteConfig {
return s.s.Config()
}
func (s *siteWrapper) Hugo() hugo.HugoInfo {
func (s *siteWrapper) Hugo() HugoInfo {
return s.s.Hugo()
}
@@ -314,11 +313,11 @@ func (s *siteWrapper) CheckReady() {
}
type testSite struct {
h hugo.HugoInfo
h HugoInfo
l *langs.Language
}
func (t testSite) Hugo() hugo.HugoInfo {
func (t testSite) Hugo() HugoInfo {
return t.h
}
@@ -451,11 +450,11 @@ func (s testSite) CheckReady() {
// NewDummyHugoSite creates a new minimal test site.
func NewDummyHugoSite(conf config.AllProvider) Site {
opts := hugo.HugoInfoOptions{
opts := HugoInfoOptions{
Conf: conf,
}
return testSite{
h: hugo.NewInfo(opts, nil),
h: NewHugoInfo(opts),
l: &langs.Language{
Lang: "en",
},
+6 -4
View File
@@ -29,7 +29,6 @@ import (
"github.com/gohugoio/hugo/common/hmaps"
"github.com/gohugoio/hugo/common/hstore"
"github.com/gohugoio/hugo/common/hugo"
"github.com/gohugoio/hugo/common/paths"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/hugofs"
@@ -75,7 +74,7 @@ func newTestPageWithFile(filename string) *testPage {
currentSection: &testPage{
sectionEntries: []string{"a", "b", "c"},
},
site: testSite{l: l},
site: &testSite{l: l},
}
}
@@ -86,7 +85,7 @@ type testPage struct {
linkTitle string
lang string
section string
site testSite
site *testSite
content string
@@ -248,7 +247,7 @@ func (p *testPage) HasShortcode(name string) bool {
panic("testpage: not implemented")
}
func (p *testPage) Hugo() hugo.HugoInfo {
func (p *testPage) Hugo() HugoInfo {
panic("testpage: not implemented")
}
@@ -528,6 +527,9 @@ func (p *testPage) SectionsPath() string {
}
func (p *testPage) Site() Site {
if p.site == nil {
panic(fmt.Sprintf("testpage: site is nil for %q", p.path))
}
return p.site
}