mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-07 20:30:36 -05:00
parent
c66dc6c74f
commit
4a3efea7ef
4 changed files with 175 additions and 4 deletions
|
@ -81,6 +81,21 @@ This means the partial will *only* be able to access those variables. The partia
|
||||||
|
|
||||||
In addition to outputting markup, partials can be used to return a value of any type. In order to return a value, a partial must include a lone `return` statement.
|
In addition to outputting markup, partials can be used to return a value of any type. In order to return a value, a partial must include a lone `return` statement.
|
||||||
|
|
||||||
|
## Inline partials
|
||||||
|
|
||||||
|
{{< new-in "0.74.0" >}}
|
||||||
|
|
||||||
|
You can also define partials inline in the template. But remember that template namespace is global, so you need to make sure that the names are unique to avoid conflicts.
|
||||||
|
|
||||||
|
```go-html-template
|
||||||
|
Value: {{ partial "my-inline-partial" . }}
|
||||||
|
|
||||||
|
{{ define "partials/my-inline-partial" }}
|
||||||
|
{{ $value := 32 }}
|
||||||
|
{{ return $value }}
|
||||||
|
{{ end }}
|
||||||
|
```
|
||||||
|
|
||||||
### Example GetFeatured
|
### Example GetFeatured
|
||||||
```go-html-template
|
```go-html-template
|
||||||
{{/* layouts/partials/GetFeatured.html */}}
|
{{/* layouts/partials/GetFeatured.html */}}
|
||||||
|
|
|
@ -65,8 +65,7 @@ func TestSiteBuildErrors(t *testing.T) {
|
||||||
fileFixer: func(content string) string {
|
fileFixer: func(content string) string {
|
||||||
return strings.Replace(content, ".Title }}", ".Title }", 1)
|
return strings.Replace(content, ".Title }}", ".Title }", 1)
|
||||||
},
|
},
|
||||||
// Base templates gets parsed at build time.
|
assertCreateError: func(a testSiteBuildErrorAsserter, err error) {
|
||||||
assertBuildError: func(a testSiteBuildErrorAsserter, err error) {
|
|
||||||
a.assertLineNumber(4, err)
|
a.assertLineNumber(4, err)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -91,7 +90,7 @@ func TestSiteBuildErrors(t *testing.T) {
|
||||||
a.c.Assert(fe.Position().LineNumber, qt.Equals, 5)
|
a.c.Assert(fe.Position().LineNumber, qt.Equals, 5)
|
||||||
a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 1)
|
a.c.Assert(fe.Position().ColumnNumber, qt.Equals, 1)
|
||||||
a.c.Assert(fe.ChromaLexer, qt.Equals, "go-html-template")
|
a.c.Assert(fe.ChromaLexer, qt.Equals, "go-html-template")
|
||||||
a.assertErrorMessage("\"layouts/foo/single.html:5:1\": parse failed: template: foo/single.html:5: unexpected \"}\" in operand", fe.Error())
|
a.assertErrorMessage("\"layouts/_default/single.html:5:1\": parse failed: template: _default/single.html.___b:5: unexpected \"}\" in operand", fe.Error())
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -597,3 +597,83 @@ func collectIdentities(set map[identity.Identity]bool, provider identity.Provide
|
||||||
func ident(level int) string {
|
func ident(level int) string {
|
||||||
return strings.Repeat(" ", level)
|
return strings.Repeat(" ", level)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPartialInline(t *testing.T) {
|
||||||
|
|
||||||
|
b := newTestSitesBuilder(t)
|
||||||
|
|
||||||
|
b.WithContent("p1.md", "")
|
||||||
|
|
||||||
|
b.WithTemplates(
|
||||||
|
"index.html", `
|
||||||
|
|
||||||
|
{{ $p1 := partial "p1" . }}
|
||||||
|
{{ $p2 := partial "p2" . }}
|
||||||
|
|
||||||
|
P1: {{ $p1 }}
|
||||||
|
P2: {{ $p2 }}
|
||||||
|
|
||||||
|
{{ define "partials/p1" }}Inline: p1{{ end }}
|
||||||
|
|
||||||
|
{{ define "partials/p2" }}
|
||||||
|
{{ $value := 32 }}
|
||||||
|
{{ return $value }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
|
||||||
|
b.CreateSites().Build(BuildCfg{})
|
||||||
|
|
||||||
|
b.AssertFileContent("public/index.html",
|
||||||
|
`
|
||||||
|
P1: Inline: p1
|
||||||
|
P2: 32`,
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPartialInlineBase(t *testing.T) {
|
||||||
|
|
||||||
|
b := newTestSitesBuilder(t)
|
||||||
|
|
||||||
|
b.WithContent("p1.md", "")
|
||||||
|
|
||||||
|
b.WithTemplates(
|
||||||
|
"baseof.html", `{{ $p3 := partial "p3" . }}P3: {{ $p3 }}
|
||||||
|
{{ block "main" . }}{{ end }}{{ define "partials/p3" }}Inline: p3{{ end }}`,
|
||||||
|
"index.html", `
|
||||||
|
{{ define "main" }}
|
||||||
|
|
||||||
|
{{ $p1 := partial "p1" . }}
|
||||||
|
{{ $p2 := partial "p2" . }}
|
||||||
|
|
||||||
|
P1: {{ $p1 }}
|
||||||
|
P2: {{ $p2 }}
|
||||||
|
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
{{ define "partials/p1" }}Inline: p1{{ end }}
|
||||||
|
|
||||||
|
{{ define "partials/p2" }}
|
||||||
|
{{ $value := 32 }}
|
||||||
|
{{ return $value }}
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
|
||||||
|
b.CreateSites().Build(BuildCfg{})
|
||||||
|
|
||||||
|
b.AssertFileContent("public/index.html",
|
||||||
|
`
|
||||||
|
P1: Inline: p1
|
||||||
|
P2: 32
|
||||||
|
P3: Inline: p3
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -553,12 +553,24 @@ func (t *templateHandler) addTemplateFile(name, path string) error {
|
||||||
if isBaseTemplatePath(name) {
|
if isBaseTemplatePath(name) {
|
||||||
// Store it for later.
|
// Store it for later.
|
||||||
t.baseof[name] = tinfo
|
t.baseof[name] = tinfo
|
||||||
|
// Also parse and add it on its own to make sure we reach the inline partials.
|
||||||
|
tinfo.name = name + ".___b"
|
||||||
|
_, err := t.addTemplateTo(tinfo, t.main)
|
||||||
|
if err != nil {
|
||||||
|
return tinfo.errWithFileContext("parse failed", err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
needsBaseof := !t.noBaseNeeded(name) && needsBaseTemplate(tinfo.template)
|
needsBaseof := !t.noBaseNeeded(name) && needsBaseTemplate(tinfo.template)
|
||||||
if needsBaseof {
|
if needsBaseof {
|
||||||
t.needsBaseof[name] = tinfo
|
t.needsBaseof[name] = tinfo
|
||||||
|
// Also parse and add it on its own to make sure we reach the inline partials.
|
||||||
|
tinfo.name = name + ".___b"
|
||||||
|
_, err := t.addTemplateTo(tinfo, t.main)
|
||||||
|
if err != nil {
|
||||||
|
return tinfo.errWithFileContext("parse failed", err)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,10 +732,51 @@ func (t *templateHandler) noBaseNeeded(name string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *templateHandler) postTransform() error {
|
func (t *templateHandler) postTransform() error {
|
||||||
|
defineCheckedHTML := false
|
||||||
|
defineCheckedText := false
|
||||||
|
|
||||||
for _, v := range t.main.templates {
|
for _, v := range t.main.templates {
|
||||||
if v.typ == templateShortcode {
|
if v.typ == templateShortcode {
|
||||||
t.addShortcodeVariant(v)
|
t.addShortcodeVariant(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if defineCheckedHTML && defineCheckedText {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
isText := isText(v.Template)
|
||||||
|
if isText {
|
||||||
|
if defineCheckedText {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defineCheckedText = true
|
||||||
|
} else {
|
||||||
|
if defineCheckedHTML {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
defineCheckedHTML = true
|
||||||
|
}
|
||||||
|
|
||||||
|
templs := templates(v.Template)
|
||||||
|
for _, templ := range templs {
|
||||||
|
if templ.Name() == "" || !strings.HasPrefix(templ.Name(), "partials/") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ts := newTemplateState(templ, templateInfo{name: templ.Name()})
|
||||||
|
ts.typ = templatePartial
|
||||||
|
|
||||||
|
if _, found := t.main.templates[templ.Name()]; !found {
|
||||||
|
// This is a template defined inline.
|
||||||
|
|
||||||
|
_, err := applyTemplateTransformers(ts, t.main.newTemplateLookup(ts))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
t.main.templates[templ.Name()] = ts
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, source := range t.transformNotFound {
|
for name, source := range t.transformNotFound {
|
||||||
|
@ -872,8 +925,13 @@ func (t *templateState) ParseInfo() tpl.ParseInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *templateState) isText() bool {
|
func (t *templateState) isText() bool {
|
||||||
_, isText := t.Template.(*texttemplate.Template)
|
return isText(t.Template)
|
||||||
|
}
|
||||||
|
|
||||||
|
func isText(templ tpl.Template) bool {
|
||||||
|
_, isText := templ.(*texttemplate.Template)
|
||||||
return isText
|
return isText
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type templateStateMap struct {
|
type templateStateMap struct {
|
||||||
|
@ -960,3 +1018,22 @@ func unwrap(templ tpl.Template) tpl.Template {
|
||||||
}
|
}
|
||||||
return templ
|
return templ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func templates(in tpl.Template) []tpl.Template {
|
||||||
|
var templs []tpl.Template
|
||||||
|
in = unwrap(in)
|
||||||
|
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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue