mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-28 21:21:40 -05:00
Add Page.RenderShortcodes
A layouts/shortcodes/include.html shortcode may look like this: ```html {{ $p := site.GetPage (.Get 0) }} {{ $p.RenderShortcodes }} ``` Fixes #7297
This commit is contained in:
parent
8fa8ce3e48
commit
ade7ec8187
14 changed files with 434 additions and 89 deletions
|
@ -114,6 +114,10 @@ func (pa pageSiteAdapter) GetPage(ref string) (page.Page, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type pageState struct {
|
type pageState struct {
|
||||||
|
// Incremented for each new page created.
|
||||||
|
// Note that this will change between builds for a given Page.
|
||||||
|
id int
|
||||||
|
|
||||||
// This slice will be of same length as the number of global slice of output
|
// This slice will be of same length as the number of global slice of output
|
||||||
// formats (for all sites).
|
// formats (for all sites).
|
||||||
pageOutputs []*pageOutput
|
pageOutputs []*pageOutput
|
||||||
|
@ -772,7 +776,7 @@ Loop:
|
||||||
currShortcode.pos = it.Pos()
|
currShortcode.pos = it.Pos()
|
||||||
currShortcode.length = iter.Current().Pos() - it.Pos()
|
currShortcode.length = iter.Current().Pos() - it.Pos()
|
||||||
if currShortcode.placeholder == "" {
|
if currShortcode.placeholder == "" {
|
||||||
currShortcode.placeholder = createShortcodePlaceholder("s", currShortcode.ordinal)
|
currShortcode.placeholder = createShortcodePlaceholder("s", p.id, currShortcode.ordinal)
|
||||||
}
|
}
|
||||||
|
|
||||||
if currShortcode.name != "" {
|
if currShortcode.name != "" {
|
||||||
|
@ -784,7 +788,7 @@ Loop:
|
||||||
currShortcode.params = s
|
currShortcode.params = s
|
||||||
}
|
}
|
||||||
|
|
||||||
currShortcode.placeholder = createShortcodePlaceholder("s", ordinal)
|
currShortcode.placeholder = createShortcodePlaceholder("s", p.id, ordinal)
|
||||||
ordinal++
|
ordinal++
|
||||||
s.shortcodes = append(s.shortcodes, currShortcode)
|
s.shortcodes = append(s.shortcodes, currShortcode)
|
||||||
|
|
||||||
|
|
|
@ -31,14 +31,19 @@ import (
|
||||||
"github.com/gohugoio/hugo/resources/page"
|
"github.com/gohugoio/hugo/resources/page"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var pageIdCounter atomic.Int64
|
||||||
|
|
||||||
func newPageBase(metaProvider *pageMeta) (*pageState, error) {
|
func newPageBase(metaProvider *pageMeta) (*pageState, error) {
|
||||||
if metaProvider.s == nil {
|
if metaProvider.s == nil {
|
||||||
panic("must provide a Site")
|
panic("must provide a Site")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
id := int(pageIdCounter.Add(1))
|
||||||
|
|
||||||
s := metaProvider.s
|
s := metaProvider.s
|
||||||
|
|
||||||
ps := &pageState{
|
ps := &pageState{
|
||||||
|
id: id,
|
||||||
pageOutput: nopPageOutput,
|
pageOutput: nopPageOutput,
|
||||||
pageOutputTemplateVariationsState: atomic.NewUint32(0),
|
pageOutputTemplateVariationsState: atomic.NewUint32(0),
|
||||||
pageCommon: &pageCommon{
|
pageCommon: &pageCommon{
|
||||||
|
|
|
@ -86,6 +86,7 @@ type pageOutput struct {
|
||||||
page.ContentProvider
|
page.ContentProvider
|
||||||
page.PageRenderProvider
|
page.PageRenderProvider
|
||||||
page.TableOfContentsProvider
|
page.TableOfContentsProvider
|
||||||
|
page.RenderShortcodesProvider
|
||||||
|
|
||||||
// May be nil.
|
// May be nil.
|
||||||
cp *pageContentOutput
|
cp *pageContentOutput
|
||||||
|
@ -99,6 +100,7 @@ func (p *pageOutput) initContentProvider(cp *pageContentOutput) {
|
||||||
p.ContentProvider = cp
|
p.ContentProvider = cp
|
||||||
p.PageRenderProvider = cp
|
p.PageRenderProvider = cp
|
||||||
p.TableOfContentsProvider = cp
|
p.TableOfContentsProvider = cp
|
||||||
|
p.RenderShortcodesProvider = cp
|
||||||
p.cp = cp
|
p.cp = cp
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,30 @@ func newPageContentOutput(p *pageState, po *pageOutput) (*pageContentOutput, err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctxCallback := func(cp2 *pageContentOutput) {
|
||||||
|
cp.p.cmap.hasNonMarkdownShortcode = cp.p.cmap.hasNonMarkdownShortcode || cp2.p.cmap.hasNonMarkdownShortcode
|
||||||
|
// Merge content placeholders
|
||||||
|
for k, v := range cp2.contentPlaceholders {
|
||||||
|
cp.contentPlaceholders[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.s.watching() {
|
||||||
|
for _, s := range cp2.p.shortcodeState.shortcodes {
|
||||||
|
for _, templ := range s.templs {
|
||||||
|
dependencyTracker.Add(templ.(identity.Manager))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer shortcode names so HasShortcode works for shortcodes from included pages.
|
||||||
|
cp.p.shortcodeState.transferNames(cp2.p.shortcodeState)
|
||||||
|
if cp2.p.pageOutputTemplateVariationsState.Load() == 2 {
|
||||||
|
cp.p.pageOutputTemplateVariationsState.Store(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = tpl.SetCallbackFunctionInContext(ctx, ctxCallback)
|
||||||
|
|
||||||
var hasVariants bool
|
var hasVariants bool
|
||||||
cp.workContent, hasVariants, err = p.contentToRender(ctx, p.source.parsed, p.cmap, cp.contentPlaceholders)
|
cp.workContent, hasVariants, err = p.contentToRender(ctx, p.source.parsed, p.cmap, cp.contentPlaceholders)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -350,6 +374,63 @@ func (p *pageContentOutput) Fragments(ctx context.Context) *tableofcontents.Frag
|
||||||
return p.tableOfContents
|
return p.tableOfContents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *pageContentOutput) RenderShortcodes(ctx context.Context) (template.HTML, error) {
|
||||||
|
p.p.s.initInit(ctx, p.initToC, p.p)
|
||||||
|
source := p.p.source.parsed.Input()
|
||||||
|
renderedShortcodes := p.contentPlaceholders
|
||||||
|
var insertPlaceholders bool
|
||||||
|
var hasVariants bool
|
||||||
|
var cb func(*pageContentOutput)
|
||||||
|
if v := tpl.GetCallbackFunctionFromContext(ctx); v != nil {
|
||||||
|
if fn, ok := v.(func(*pageContentOutput)); ok {
|
||||||
|
insertPlaceholders = true
|
||||||
|
cb = fn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c := make([]byte, 0, len(source)+(len(source)/10))
|
||||||
|
for _, it := range p.p.cmap.items {
|
||||||
|
switch v := it.(type) {
|
||||||
|
case pageparser.Item:
|
||||||
|
c = append(c, source[v.Pos():v.Pos()+len(v.Val(source))]...)
|
||||||
|
case pageContentReplacement:
|
||||||
|
// Ignore.
|
||||||
|
case *shortcode:
|
||||||
|
if !insertPlaceholders || !v.insertPlaceholder() {
|
||||||
|
// Insert the rendered shortcode.
|
||||||
|
renderedShortcode, found := renderedShortcodes[v.placeholder]
|
||||||
|
if !found {
|
||||||
|
// This should never happen.
|
||||||
|
panic(fmt.Sprintf("rendered shortcode %q not found", v.placeholder))
|
||||||
|
}
|
||||||
|
|
||||||
|
b, more, err := renderedShortcode.renderShortcode(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to render shortcode: %w", err)
|
||||||
|
}
|
||||||
|
hasVariants = hasVariants || more
|
||||||
|
c = append(c, []byte(b)...)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Insert the placeholder so we can insert the content after
|
||||||
|
// markdown processing.
|
||||||
|
c = append(c, []byte(v.placeholder)...)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unknown item type %T", it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasVariants {
|
||||||
|
p.p.pageOutputTemplateVariationsState.Store(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
if cb != nil {
|
||||||
|
cb(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
return helpers.BytesToHTML(c), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *pageContentOutput) TableOfContents(ctx context.Context) template.HTML {
|
func (p *pageContentOutput) TableOfContents(ctx context.Context) template.HTML {
|
||||||
p.p.s.initInit(ctx, p.initToC, p.p)
|
p.p.s.initInit(ctx, p.initToC, p.p)
|
||||||
return p.tableOfContentsHTML
|
return p.tableOfContentsHTML
|
||||||
|
|
|
@ -1998,7 +1998,6 @@ func TestRenderWithoutArgument(t *testing.T) {
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
},
|
},
|
||||||
).BuildE()
|
).BuildE()
|
||||||
|
|
||||||
|
|
232
hugolib/rendershortcodes_test.go
Normal file
232
hugolib/rendershortcodes_test.go
Normal file
|
@ -0,0 +1,232 @@
|
||||||
|
// 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 (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRenderShortcodesBasic(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
files := `
|
||||||
|
-- hugo.toml --
|
||||||
|
disableKinds = ["home", "taxonomy", "term"]
|
||||||
|
-- content/p1.md --
|
||||||
|
---
|
||||||
|
title: "p1"
|
||||||
|
---
|
||||||
|
## p1-h1
|
||||||
|
{{% include "p2" %}}
|
||||||
|
-- content/p2.md --
|
||||||
|
---
|
||||||
|
title: "p2"
|
||||||
|
---
|
||||||
|
### p2-h1
|
||||||
|
{{< withhtml >}}
|
||||||
|
### p2-h2
|
||||||
|
{{% withmarkdown %}}
|
||||||
|
### p2-h3
|
||||||
|
{{% include "p3" %}}
|
||||||
|
-- content/p3.md --
|
||||||
|
---
|
||||||
|
title: "p3"
|
||||||
|
---
|
||||||
|
### p3-h1
|
||||||
|
{{< withhtml >}}
|
||||||
|
### p3-h2
|
||||||
|
{{% withmarkdown %}}
|
||||||
|
{{< level3 >}}
|
||||||
|
-- layouts/shortcodes/include.html --
|
||||||
|
{{ $p := site.GetPage (.Get 0) }}
|
||||||
|
{{ $p.RenderShortcodes }}
|
||||||
|
-- layouts/shortcodes/withhtml.html --
|
||||||
|
<div>{{ .Page.Title }} withhtml</div>
|
||||||
|
-- layouts/shortcodes/withmarkdown.html --
|
||||||
|
#### {{ .Page.Title }} withmarkdown
|
||||||
|
-- layouts/shortcodes/level3.html --
|
||||||
|
Level 3: {{ .Page.Title }}
|
||||||
|
-- layouts/_default/single.html --
|
||||||
|
Fragments: {{ .Fragments.Identifiers }}|
|
||||||
|
HasShortcode Level 1: {{ .HasShortcode "include" }}|
|
||||||
|
HasShortcode Level 2: {{ .HasShortcode "withmarkdown" }}|
|
||||||
|
HasShortcode Level 3: {{ .HasShortcode "level3" }}|
|
||||||
|
HasSHortcode not found: {{ .HasShortcode "notfound" }}|
|
||||||
|
Content: {{ .Content }}|
|
||||||
|
`
|
||||||
|
|
||||||
|
b := NewIntegrationTestBuilder(
|
||||||
|
IntegrationTestConfig{
|
||||||
|
T: t,
|
||||||
|
TxtarString: files,
|
||||||
|
},
|
||||||
|
).Build()
|
||||||
|
|
||||||
|
b.AssertFileContent("public/p1/index.html",
|
||||||
|
"Fragments: [p1-h1 p2-h1 p2-h2 p2-h3 p2-withmarkdown p3-h1 p3-h2 p3-withmarkdown]|",
|
||||||
|
"HasShortcode Level 1: true|",
|
||||||
|
"HasShortcode Level 2: true|",
|
||||||
|
"HasShortcode Level 3: true|",
|
||||||
|
"HasSHortcode not found: false|",
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO1 more assertions.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderShortcodesNestedMultipleOutputFormatTemplates(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
files := `
|
||||||
|
-- hugo.toml --
|
||||||
|
disableKinds = ["home", "taxonomy", "term", "section", "rss", "sitemap", "robotsTXT", "404"]
|
||||||
|
[outputs]
|
||||||
|
page = ["html", "json"]
|
||||||
|
-- content/p1.md --
|
||||||
|
---
|
||||||
|
title: "p1"
|
||||||
|
---
|
||||||
|
## p1-h1
|
||||||
|
{{% include "p2" %}}
|
||||||
|
-- content/p2.md --
|
||||||
|
---
|
||||||
|
title: "p2"
|
||||||
|
---
|
||||||
|
### p2-h1
|
||||||
|
{{% myshort %}}
|
||||||
|
-- layouts/shortcodes/include.html --
|
||||||
|
{{ $p := site.GetPage (.Get 0) }}
|
||||||
|
{{ $p.RenderShortcodes }}
|
||||||
|
-- layouts/shortcodes/myshort.html --
|
||||||
|
Myshort HTML.
|
||||||
|
-- layouts/shortcodes/myshort.json --
|
||||||
|
Myshort JSON.
|
||||||
|
-- layouts/_default/single.html --
|
||||||
|
HTML: {{ .Content }}
|
||||||
|
-- layouts/_default/single.json --
|
||||||
|
JSON: {{ .Content }}
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
b := NewIntegrationTestBuilder(
|
||||||
|
IntegrationTestConfig{
|
||||||
|
T: t,
|
||||||
|
TxtarString: files,
|
||||||
|
},
|
||||||
|
).Build()
|
||||||
|
|
||||||
|
b.AssertFileContent("public/p1/index.html", "Myshort HTML")
|
||||||
|
b.AssertFileContent("public/p1/index.json", "Myshort JSON")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderShortcodesEditNested(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
files := `
|
||||||
|
-- hugo.toml --
|
||||||
|
disableLiveReload = true
|
||||||
|
disableKinds = ["home", "taxonomy", "term", "section", "rss", "sitemap", "robotsTXT", "404"]
|
||||||
|
-- content/p1.md --
|
||||||
|
---
|
||||||
|
title: "p1"
|
||||||
|
---
|
||||||
|
## p1-h1
|
||||||
|
{{% include "p2" %}}
|
||||||
|
-- content/p2.md --
|
||||||
|
---
|
||||||
|
title: "p2"
|
||||||
|
---
|
||||||
|
### p2-h1
|
||||||
|
{{% myshort %}}
|
||||||
|
-- layouts/shortcodes/include.html --
|
||||||
|
{{ $p := site.GetPage (.Get 0) }}
|
||||||
|
{{ $p.RenderShortcodes }}
|
||||||
|
-- layouts/shortcodes/myshort.html --
|
||||||
|
Myshort Original.
|
||||||
|
-- layouts/_default/single.html --
|
||||||
|
{{ .Content }}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
b := NewIntegrationTestBuilder(
|
||||||
|
IntegrationTestConfig{
|
||||||
|
T: t,
|
||||||
|
TxtarString: files,
|
||||||
|
Running: true,
|
||||||
|
},
|
||||||
|
).Build()
|
||||||
|
|
||||||
|
b.AssertFileContent("public/p1/index.html", "Myshort Original.")
|
||||||
|
|
||||||
|
b.EditFileReplace("layouts/shortcodes/myshort.html", func(s string) string {
|
||||||
|
return "Myshort Edited."
|
||||||
|
})
|
||||||
|
b.Build()
|
||||||
|
b.AssertFileContent("public/p1/index.html", "Myshort Edited.")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderShortcodesEditIncludedPage(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
files := `
|
||||||
|
-- hugo.toml --
|
||||||
|
disableLiveReload = true
|
||||||
|
disableKinds = ["home", "taxonomy", "term", "section", "rss", "sitemap", "robotsTXT", "404"]
|
||||||
|
-- content/p1.md --
|
||||||
|
---
|
||||||
|
title: "p1"
|
||||||
|
---
|
||||||
|
## p1-h1
|
||||||
|
{{% include "p2" %}}
|
||||||
|
-- content/p2.md --
|
||||||
|
---
|
||||||
|
title: "p2"
|
||||||
|
---
|
||||||
|
### Original
|
||||||
|
{{% myshort %}}
|
||||||
|
-- layouts/shortcodes/include.html --
|
||||||
|
{{ $p := site.GetPage (.Get 0) }}
|
||||||
|
{{ $p.RenderShortcodes }}
|
||||||
|
-- layouts/shortcodes/myshort.html --
|
||||||
|
Myshort Original.
|
||||||
|
-- layouts/_default/single.html --
|
||||||
|
{{ .Content }}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
`
|
||||||
|
|
||||||
|
b := NewIntegrationTestBuilder(
|
||||||
|
IntegrationTestConfig{
|
||||||
|
T: t,
|
||||||
|
TxtarString: files,
|
||||||
|
Running: true,
|
||||||
|
},
|
||||||
|
).Build()
|
||||||
|
|
||||||
|
b.AssertFileContent("public/p1/index.html", "Original")
|
||||||
|
|
||||||
|
b.EditFileReplace("content/p2.md", func(s string) string {
|
||||||
|
return strings.Replace(s, "Original", "Edited", 1)
|
||||||
|
})
|
||||||
|
b.Build()
|
||||||
|
b.AssertFileContent("public/p1/index.html", "Edited")
|
||||||
|
|
||||||
|
}
|
|
@ -185,8 +185,8 @@ func (scp *ShortcodeWithPage) page() page.Page {
|
||||||
// Note - this value must not contain any markup syntax
|
// Note - this value must not contain any markup syntax
|
||||||
const shortcodePlaceholderPrefix = "HAHAHUGOSHORTCODE"
|
const shortcodePlaceholderPrefix = "HAHAHUGOSHORTCODE"
|
||||||
|
|
||||||
func createShortcodePlaceholder(id string, ordinal int) string {
|
func createShortcodePlaceholder(sid string, id, ordinal int) string {
|
||||||
return shortcodePlaceholderPrefix + id + strconv.Itoa(ordinal) + "HBHB"
|
return shortcodePlaceholderPrefix + strconv.Itoa(id) + sid + strconv.Itoa(ordinal) + "HBHB"
|
||||||
}
|
}
|
||||||
|
|
||||||
type shortcode struct {
|
type shortcode struct {
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// A placeholder for the TableOfContents markup. This is what we pass to the Goldmark etc. renderers.
|
// A placeholder for the TableOfContents markup. This is what we pass to the Goldmark etc. renderers.
|
||||||
var tocShortcodePlaceholder = createShortcodePlaceholder("TOC", 0)
|
var tocShortcodePlaceholder = createShortcodePlaceholder("TOC", 0, 0)
|
||||||
|
|
||||||
// shortcodeRenderer is typically used to delay rendering of inner shortcodes
|
// shortcodeRenderer is typically used to delay rendering of inner shortcodes
|
||||||
// marked with placeholders in the content.
|
// marked with placeholders in the content.
|
||||||
|
|
|
@ -948,7 +948,6 @@ title: "p1"
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
||||||
|
@ -991,7 +990,6 @@ title: "p1"
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
||||||
|
@ -1023,7 +1021,6 @@ echo "foo";
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
||||||
|
@ -1061,7 +1058,6 @@ title: "p1"
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
||||||
|
@ -1098,7 +1094,7 @@ Title: {{ .Get "title" | safeHTML }}
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
Verbose: true,
|
Verbose: true,
|
||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
@ -1191,7 +1187,7 @@ C'est un test
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
Verbose: true,
|
Verbose: true,
|
||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
@ -1229,7 +1225,7 @@ InnerDeindent: {{ .Get 0 }}: {{ len .InnerDeindent }}
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
Verbose: true,
|
Verbose: true,
|
||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
@ -1269,7 +1265,7 @@ Inner: {{ .Get 0 }}: {{ len .Inner }}
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
Verbose: true,
|
Verbose: true,
|
||||||
},
|
},
|
||||||
).BuildE()
|
).BuildE()
|
||||||
|
@ -1306,7 +1302,7 @@ Hello.
|
||||||
IntegrationTestConfig{
|
IntegrationTestConfig{
|
||||||
T: t,
|
T: t,
|
||||||
TxtarString: files,
|
TxtarString: files,
|
||||||
Running: true,
|
|
||||||
Verbose: true,
|
Verbose: true,
|
||||||
},
|
},
|
||||||
).Build()
|
).Build()
|
||||||
|
|
|
@ -277,6 +277,7 @@ type PageRenderProvider interface {
|
||||||
// PageWithoutContent is the Page without any of the content methods.
|
// PageWithoutContent is the Page without any of the content methods.
|
||||||
type PageWithoutContent interface {
|
type PageWithoutContent interface {
|
||||||
RawContentProvider
|
RawContentProvider
|
||||||
|
RenderShortcodesProvider
|
||||||
resource.Resource
|
resource.Resource
|
||||||
PageMetaProvider
|
PageMetaProvider
|
||||||
resource.LanguageProvider
|
resource.LanguageProvider
|
||||||
|
@ -362,6 +363,11 @@ type RawContentProvider interface {
|
||||||
RawContent() string
|
RawContent() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RenderShortcodesProvider interface {
|
||||||
|
// RenderShortcodes returns RawContent with any shortcodes rendered.
|
||||||
|
RenderShortcodes(context.Context) (template.HTML, error)
|
||||||
|
}
|
||||||
|
|
||||||
// RefProvider provides the methods needed to create reflinks to pages.
|
// RefProvider provides the methods needed to create reflinks to pages.
|
||||||
type RefProvider interface {
|
type RefProvider interface {
|
||||||
// Ref returns an absolute URl to a page.
|
// Ref returns an absolute URl to a page.
|
||||||
|
|
|
@ -401,6 +401,10 @@ func (p *nopPage) RawContent() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *nopPage) RenderShortcodes(ctx context.Context) (template.HTML, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
func (p *nopPage) ReadingTime(context.Context) int {
|
func (p *nopPage) ReadingTime(context.Context) int {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,15 +118,15 @@ func (p *testPage) Err() resource.ResourceError {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Aliases() []string {
|
func (p *testPage) Aliases() []string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) AllTranslations() Pages {
|
func (p *testPage) AllTranslations() Pages {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) AlternativeOutputFormats() OutputFormats {
|
func (p *testPage) AlternativeOutputFormats() OutputFormats {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Author() Author {
|
func (p *testPage) Author() Author {
|
||||||
|
@ -138,19 +138,19 @@ func (p *testPage) Authors() AuthorList {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) BaseFileName() string {
|
func (p *testPage) BaseFileName() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) BundleType() files.ContentClass {
|
func (p *testPage) BundleType() files.ContentClass {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Content(context.Context) (any, error) {
|
func (p *testPage) Content(context.Context) (any, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) ContentBaseName() string {
|
func (p *testPage) ContentBaseName() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) CurrentSection() Page {
|
func (p *testPage) CurrentSection() Page {
|
||||||
|
@ -178,11 +178,11 @@ func (p *testPage) Description() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Dir() string {
|
func (p *testPage) Dir() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Draft() bool {
|
func (p *testPage) Draft() bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Eq(other any) bool {
|
func (p *testPage) Eq(other any) bool {
|
||||||
|
@ -194,11 +194,11 @@ func (p *testPage) ExpiryDate() time.Time {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Ext() string {
|
func (p *testPage) Ext() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Extension() string {
|
func (p *testPage) Extension() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) File() source.File {
|
func (p *testPage) File() source.File {
|
||||||
|
@ -206,15 +206,15 @@ func (p *testPage) File() source.File {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) FileInfo() hugofs.FileMetaInfo {
|
func (p *testPage) FileInfo() hugofs.FileMetaInfo {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Filename() string {
|
func (p *testPage) Filename() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) FirstSection() Page {
|
func (p *testPage) FirstSection() Page {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) FuzzyWordCount(context.Context) int {
|
func (p *testPage) FuzzyWordCount(context.Context) int {
|
||||||
|
@ -222,19 +222,19 @@ func (p *testPage) FuzzyWordCount(context.Context) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) GetPage(ref string) (Page, error) {
|
func (p *testPage) GetPage(ref string) (Page, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) GetPageWithTemplateInfo(info tpl.Info, ref string) (Page, error) {
|
func (p *testPage) GetPageWithTemplateInfo(info tpl.Info, ref string) (Page, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) GetParam(key string) any {
|
func (p *testPage) GetParam(key string) any {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) GetTerms(taxonomy string) Pages {
|
func (p *testPage) GetTerms(taxonomy string) Pages {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) GetRelatedDocsHandler() *RelatedDocsHandler {
|
func (p *testPage) GetRelatedDocsHandler() *RelatedDocsHandler {
|
||||||
|
@ -250,27 +250,27 @@ func (p *testPage) CodeOwners() []string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) HasMenuCurrent(menuID string, me *navigation.MenuEntry) bool {
|
func (p *testPage) HasMenuCurrent(menuID string, me *navigation.MenuEntry) bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) HasShortcode(name string) bool {
|
func (p *testPage) HasShortcode(name string) bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Hugo() hugo.HugoInfo {
|
func (p *testPage) Hugo() hugo.HugoInfo {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) InSection(other any) (bool, error) {
|
func (p *testPage) InSection(other any) (bool, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) IsAncestor(other any) (bool, error) {
|
func (p *testPage) IsAncestor(other any) (bool, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) IsDescendant(other any) (bool, error) {
|
func (p *testPage) IsDescendant(other any) (bool, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) IsDraft() bool {
|
func (p *testPage) IsDraft() bool {
|
||||||
|
@ -278,27 +278,27 @@ func (p *testPage) IsDraft() bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) IsHome() bool {
|
func (p *testPage) IsHome() bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) IsMenuCurrent(menuID string, inme *navigation.MenuEntry) bool {
|
func (p *testPage) IsMenuCurrent(menuID string, inme *navigation.MenuEntry) bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) IsNode() bool {
|
func (p *testPage) IsNode() bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) IsPage() bool {
|
func (p *testPage) IsPage() bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) IsSection() bool {
|
func (p *testPage) IsSection() bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) IsTranslated() bool {
|
func (p *testPage) IsTranslated() bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Keywords() []string {
|
func (p *testPage) Keywords() []string {
|
||||||
|
@ -314,7 +314,7 @@ func (p *testPage) Lang() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Language() *langs.Language {
|
func (p *testPage) Language() *langs.Language {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) LanguagePrefix() string {
|
func (p *testPage) LanguagePrefix() string {
|
||||||
|
@ -348,11 +348,11 @@ func (p *testPage) LinkTitle() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) LogicalName() string {
|
func (p *testPage) LogicalName() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) MediaType() media.Type {
|
func (p *testPage) MediaType() media.Type {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Menus() navigation.PageMenus {
|
func (p *testPage) Menus() navigation.PageMenus {
|
||||||
|
@ -360,11 +360,11 @@ func (p *testPage) Menus() navigation.PageMenus {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Name() string {
|
func (p *testPage) Name() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Next() Page {
|
func (p *testPage) Next() Page {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) NextInSection() Page {
|
func (p *testPage) NextInSection() Page {
|
||||||
|
@ -376,19 +376,19 @@ func (p *testPage) NextPage() Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) OutputFormats() OutputFormats {
|
func (p *testPage) OutputFormats() OutputFormats {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Pages() Pages {
|
func (p *testPage) Pages() Pages {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) RegularPages() Pages {
|
func (p *testPage) RegularPages() Pages {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) RegularPagesRecursive() Pages {
|
func (p *testPage) RegularPagesRecursive() Pages {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Paginate(seq any, options ...any) (*Pager, error) {
|
func (p *testPage) Paginate(seq any, options ...any) (*Pager, error) {
|
||||||
|
@ -412,11 +412,11 @@ func (p *testPage) Page() Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Parent() Page {
|
func (p *testPage) Parent() Page {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Ancestors() Pages {
|
func (p *testPage) Ancestors() Pages {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Path() string {
|
func (p *testPage) Path() string {
|
||||||
|
@ -428,19 +428,19 @@ func (p *testPage) Pathc() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Permalink() string {
|
func (p *testPage) Permalink() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Plain(context.Context) string {
|
func (p *testPage) Plain(context.Context) string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) PlainWords(context.Context) []string {
|
func (p *testPage) PlainWords(context.Context) []string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Prev() Page {
|
func (p *testPage) Prev() Page {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) PrevInSection() Page {
|
func (p *testPage) PrevInSection() Page {
|
||||||
|
@ -460,15 +460,19 @@ func (p *testPage) RSSLink() template.URL {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) RawContent() string {
|
func (p *testPage) RawContent() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *testPage) RenderShortcodes(context.Context) (template.HTML, error) {
|
||||||
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) ReadingTime(context.Context) int {
|
func (p *testPage) ReadingTime(context.Context) int {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Ref(argsm map[string]any) (string, error) {
|
func (p *testPage) Ref(argsm map[string]any) (string, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) RefFrom(argsm map[string]any, source any) (string, error) {
|
func (p *testPage) RefFrom(argsm map[string]any, source any) (string, error) {
|
||||||
|
@ -476,11 +480,11 @@ func (p *testPage) RefFrom(argsm map[string]any, source any) (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) RelPermalink() string {
|
func (p *testPage) RelPermalink() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) RelRef(argsm map[string]any) (string, error) {
|
func (p *testPage) RelRef(argsm map[string]any) (string, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) RelRefFrom(argsm map[string]any, source any) (string, error) {
|
func (p *testPage) RelRefFrom(argsm map[string]any, source any) (string, error) {
|
||||||
|
@ -488,27 +492,27 @@ func (p *testPage) RelRefFrom(argsm map[string]any, source any) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Render(ctx context.Context, layout ...string) (template.HTML, error) {
|
func (p *testPage) Render(ctx context.Context, layout ...string) (template.HTML, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) RenderString(ctx context.Context, args ...any) (template.HTML, error) {
|
func (p *testPage) RenderString(ctx context.Context, args ...any) (template.HTML, error) {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) ResourceType() string {
|
func (p *testPage) ResourceType() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Resources() resource.Resources {
|
func (p *testPage) Resources() resource.Resources {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Scratch() *maps.Scratch {
|
func (p *testPage) Scratch() *maps.Scratch {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Store() *maps.Scratch {
|
func (p *testPage) Store() *maps.Scratch {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) RelatedKeywords(cfg related.IndexConfig) ([]related.Keyword, error) {
|
func (p *testPage) RelatedKeywords(cfg related.IndexConfig) ([]related.Keyword, error) {
|
||||||
|
@ -525,7 +529,7 @@ func (p *testPage) Section() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Sections() Pages {
|
func (p *testPage) Sections() Pages {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) SectionsEntries() []string {
|
func (p *testPage) SectionsEntries() []string {
|
||||||
|
@ -541,7 +545,7 @@ func (p *testPage) Site() Site {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Sites() Sites {
|
func (p *testPage) Sites() Sites {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Slug() string {
|
func (p *testPage) Slug() string {
|
||||||
|
@ -553,11 +557,11 @@ func (p *testPage) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Summary(context.Context) template.HTML {
|
func (p *testPage) Summary(context.Context) template.HTML {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) TableOfContents(context.Context) template.HTML {
|
func (p *testPage) TableOfContents(context.Context) template.HTML {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Title() string {
|
func (p *testPage) Title() string {
|
||||||
|
@ -565,7 +569,7 @@ func (p *testPage) Title() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) TranslationBaseName() string {
|
func (p *testPage) TranslationBaseName() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) TranslationKey() string {
|
func (p *testPage) TranslationKey() string {
|
||||||
|
@ -573,11 +577,11 @@ func (p *testPage) TranslationKey() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Translations() Pages {
|
func (p *testPage) Translations() Pages {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Truncated(context.Context) bool {
|
func (p *testPage) Truncated(context.Context) bool {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Type() string {
|
func (p *testPage) Type() string {
|
||||||
|
@ -589,7 +593,7 @@ func (p *testPage) URL() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) UniqueID() string {
|
func (p *testPage) UniqueID() string {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) Weight() int {
|
func (p *testPage) Weight() int {
|
||||||
|
@ -597,11 +601,11 @@ func (p *testPage) Weight() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) WordCount(context.Context) int {
|
func (p *testPage) WordCount(context.Context) int {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *testPage) GetIdentity() identity.Identity {
|
func (p *testPage) GetIdentity() identity.Identity {
|
||||||
panic("tespage: not implemented")
|
panic("testpage: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTestPages(num int) Pages {
|
func createTestPages(num int) Pages {
|
||||||
|
|
|
@ -63,6 +63,7 @@ type (
|
||||||
pageContextKeyType string
|
pageContextKeyType string
|
||||||
hasLockContextKeyType string
|
hasLockContextKeyType string
|
||||||
stackContextKeyType string
|
stackContextKeyType string
|
||||||
|
callbackContextKeyType string
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -70,6 +71,9 @@ const (
|
||||||
PageContextKey = pageContextKeyType("page")
|
PageContextKey = pageContextKeyType("page")
|
||||||
// Used in partialCached to signal to nested templates that a lock is already taken.
|
// Used in partialCached to signal to nested templates that a lock is already taken.
|
||||||
HasLockContextKey = hasLockContextKeyType("hasLock")
|
HasLockContextKey = hasLockContextKeyType("hasLock")
|
||||||
|
|
||||||
|
// Used to pass down a callback function to nested templates.
|
||||||
|
CallbackContextKey = callbackContextKeyType("callback")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Note: The context is currently not fully implemented in Hugo. This is a work in progress.
|
// Note: The context is currently not fully implemented in Hugo. This is a work in progress.
|
||||||
|
|
|
@ -191,6 +191,14 @@ func SetHasLockInContext(ctx context.Context, hasLock bool) context.Context {
|
||||||
return context.WithValue(ctx, texttemplate.HasLockContextKey, hasLock)
|
return context.WithValue(ctx, texttemplate.HasLockContextKey, hasLock)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetCallbackFunctionFromContext(ctx context.Context) any {
|
||||||
|
return ctx.Value(texttemplate.CallbackContextKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetCallbackFunctionInContext(ctx context.Context, fn any) context.Context {
|
||||||
|
return context.WithValue(ctx, texttemplate.CallbackContextKey, fn)
|
||||||
|
}
|
||||||
|
|
||||||
const hugoNewLinePlaceholder = "___hugonl_"
|
const hugoNewLinePlaceholder = "___hugonl_"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
Loading…
Reference in a new issue