diff --git a/hugolib/page.go b/hugolib/page.go index aa107c63e..a80b28a3e 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -17,7 +17,6 @@ import ( "bytes" "context" "fmt" - "html/template" "path" "path/filepath" "sort" @@ -151,19 +150,6 @@ func (p *pageState) GetIdentity() identity.Identity { return identity.NewPathIdentity(files.ComponentFolderContent, filepath.FromSlash(p.Pathc())) } -func (p *pageState) Fragments(ctx context.Context) *tableofcontents.Fragments { - p.s.initInit(ctx, p.cp.initToC, p) - if p.pageOutput.cp.tableOfContents == nil { - return tableofcontents.Empty - } - return p.pageOutput.cp.tableOfContents -} - -func (p *pageState) TableOfContents(ctx context.Context) template.HTML { - p.s.initInit(ctx, p.cp.initToC, p) - return p.pageOutput.cp.tableOfContentsHTML -} - func (p *pageState) HeadingsFiltered(context.Context) tableofcontents.Headings { return nil } @@ -957,6 +943,7 @@ func (p *pageState) shiftToOutputFormat(isRenderingSite bool, idx int) error { p.pageOutput.contentRenderer = lcp p.pageOutput.ContentProvider = lcp p.pageOutput.PageRenderProvider = lcp + p.pageOutput.TableOfContentsProvider = lcp } } diff --git a/hugolib/page__fragments_test.go b/hugolib/page__fragments_test.go new file mode 100644 index 000000000..4b17378d5 --- /dev/null +++ b/hugolib/page__fragments_test.go @@ -0,0 +1,69 @@ +// Copyright 2023 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 hugolib + +import "testing" + +// #10794 +func TestFragmentsAndToCCrossSiteAccess(t *testing.T) { + files := ` +-- hugo.toml -- +baseURL = "https://example.com" +disableKinds = ["taxonomy", "term", "home"] +defaultContentLanguage = "en" +defaultContentLanguageInSubdir = true +[languages] +[languages.en] +weight = 1 +[languages.fr] +weight = 2 +-- content/p1.en.md -- +--- +title: "P1" +outputs: ["HTML", "JSON"] +--- + +## Heading 1 EN + +-- content/p1.fr.md -- +--- +title: "P1" +outputs: ["HTML", "JSON"] +--- + +## Heading 1 FR +-- layouts/_default/single.html -- +HTML +-- layouts/_default/single.json -- +{{ $secondSite := index .Sites 1 }} +{{ $p1 := $secondSite.GetPage "p1" }} +ToC: {{ $p1.TableOfContents }} +Fragments : {{ $p1.Fragments.Identifiers }} + + + + +` + + b := NewIntegrationTestBuilder( + IntegrationTestConfig{ + TxtarString: files, + T: t, + }, + ).Build() + + b.AssertFileContent("public/en/p1/index.html", "HTML") + b.AssertFileContent("public/en/p1/index.json", "ToC: \nFragments : [heading-1-fr]") + +} diff --git a/hugolib/page__output.go b/hugolib/page__output.go index ae2fdb778..25ce26b7a 100644 --- a/hugolib/page__output.go +++ b/hugolib/page__output.go @@ -54,12 +54,13 @@ func newPageOutput( } po := &pageOutput{ - f: f, - pagePerOutputProviders: providers, - ContentProvider: page.NopPage, - PageRenderProvider: page.NopPage, - render: render, - paginator: pag, + f: f, + pagePerOutputProviders: providers, + ContentProvider: page.NopPage, + PageRenderProvider: page.NopPage, + TableOfContentsProvider: page.NopPage, + render: render, + paginator: pag, } return po @@ -84,6 +85,7 @@ type pageOutput struct { pagePerOutputProviders page.ContentProvider page.PageRenderProvider + page.TableOfContentsProvider // May be nil. cp *pageContentOutput @@ -96,6 +98,7 @@ func (p *pageOutput) initContentProvider(cp *pageContentOutput) { p.contentRenderer = cp p.ContentProvider = cp p.PageRenderProvider = cp + p.TableOfContentsProvider = cp p.cp = cp } diff --git a/hugolib/page__per_output.go b/hugolib/page__per_output.go index be65ad9e7..3e61a4513 100644 --- a/hugolib/page__per_output.go +++ b/hugolib/page__per_output.go @@ -342,6 +342,19 @@ func (p *pageContentOutput) Reset() { p.renderHooks = &renderHooks{} } +func (p *pageContentOutput) Fragments(ctx context.Context) *tableofcontents.Fragments { + p.p.s.initInit(ctx, p.initToC, p.p) + if p.tableOfContents == nil { + return tableofcontents.Empty + } + return p.tableOfContents +} + +func (p *pageContentOutput) TableOfContents(ctx context.Context) template.HTML { + p.p.s.initInit(ctx, p.initToC, p.p) + return p.tableOfContentsHTML +} + func (p *pageContentOutput) Content(ctx context.Context) (any, error) { p.p.s.initInit(ctx, p.initMain, p.p) return p.content, nil @@ -380,11 +393,6 @@ func (p *pageContentOutput) Summary(ctx context.Context) template.HTML { return p.summary } -func (p *pageContentOutput) TableOfContents(ctx context.Context) template.HTML { - p.p.s.initInit(ctx, p.initMain, p.p) - return p.tableOfContentsHTML -} - func (p *pageContentOutput) Truncated(ctx context.Context) bool { if p.p.truncated { return true diff --git a/hugolib/shortcode_page.go b/hugolib/shortcode_page.go index 3bc061bc0..20fa22d2f 100644 --- a/hugolib/shortcode_page.go +++ b/hugolib/shortcode_page.go @@ -63,6 +63,7 @@ var zeroShortcode = prerenderedShortcode{} // the best we can do. type pageForShortcode struct { page.PageWithoutContent + page.TableOfContentsProvider page.ContentProvider // We need to replace it after we have rendered it, so provide a @@ -74,10 +75,11 @@ type pageForShortcode struct { func newPageForShortcode(p *pageState) page.Page { return &pageForShortcode{ - PageWithoutContent: p, - ContentProvider: page.NopPage, - toc: template.HTML(tocShortcodePlaceholder), - p: p, + PageWithoutContent: p, + TableOfContentsProvider: p, + ContentProvider: page.NopPage, + toc: template.HTML(tocShortcodePlaceholder), + p: p, } } @@ -105,7 +107,7 @@ func newPageForRenderHook(p *pageState) page.Page { return &pageForRenderHooks{ PageWithoutContent: p, ContentProvider: page.NopPage, - TableOfContentsProvider: page.NopPage, + TableOfContentsProvider: p, } } diff --git a/resources/page/page.go b/resources/page/page.go index 8f89142b3..6f6f1d100 100644 --- a/resources/page/page.go +++ b/resources/page/page.go @@ -334,9 +334,6 @@ type PageWithoutContent interface { // Used in change/dependency tracking. identity.Provider - // Fragments returns the fragments for this page. - Fragments(context.Context) *tableofcontents.Fragments - // Headings returns the headings for this page when a filter is set. // This is currently only triggered with the Related content feature // and the "fragments" type of index. @@ -407,6 +404,9 @@ type SitesProvider interface { type TableOfContentsProvider interface { // TableOfContents returns the table of contents for the page rendered as HTML. TableOfContents(context.Context) template.HTML + + // Fragments returns the fragments for this page. + Fragments(context.Context) *tableofcontents.Fragments } // TranslationsProvider provides access to any translations. diff --git a/resources/page/page_lazy_contentprovider.go b/resources/page/page_lazy_contentprovider.go index 400b9e4f0..2d647e90c 100644 --- a/resources/page/page_lazy_contentprovider.go +++ b/resources/page/page_lazy_contentprovider.go @@ -19,6 +19,7 @@ import ( "github.com/gohugoio/hugo/lazy" "github.com/gohugoio/hugo/markup/converter" + "github.com/gohugoio/hugo/markup/tableofcontents" ) // OutputFormatContentProvider represents the method set that is "outputFormat aware" and that we @@ -73,6 +74,17 @@ func (lcp *LazyContentProvider) Reset() { lcp.init.Reset() } +func (lcp *LazyContentProvider) TableOfContents(ctx context.Context) template.HTML { + lcp.init.Do(ctx) + return lcp.cp.TableOfContents(ctx) + +} + +func (lcp *LazyContentProvider) Fragments(ctx context.Context) *tableofcontents.Fragments { + lcp.init.Do(ctx) + return lcp.cp.Fragments(ctx) +} + func (lcp *LazyContentProvider) Content(ctx context.Context) (any, error) { lcp.init.Do(ctx) return lcp.cp.Content(ctx)