Skip to content

Commit

Permalink
Add render template hooks for links and images
Browse files Browse the repository at this point in the history
This commit also revises the change detection for templates used by content files in server mode.

Fixes gohugoio#6545
Fixes gohugoio#4663
Closes gohugoio#6043
  • Loading branch information
bep committed Dec 18, 2019
1 parent 67f3aa7 commit d3cf3f7
Show file tree
Hide file tree
Showing 62 changed files with 2,162 additions and 524 deletions.
4 changes: 4 additions & 0 deletions deps/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ func (d Deps) ForLanguage(cfg DepsCfg, onCreated func(d *Deps) error) (*Deps, er
return nil, err
}

if err != nil {
return nil, err
}

d.Site = cfg.Site

// The resource cache is global so reuse.
Expand Down
4 changes: 3 additions & 1 deletion helpers/content.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ import (

"github.com/gohugoio/hugo/common/loggers"

"github.com/spf13/afero"

"github.com/gohugoio/hugo/markup/converter"

"github.com/gohugoio/hugo/markup"

bp "github.com/gohugoio/hugo/bufferpool"
"github.com/gohugoio/hugo/config"
"github.com/spf13/afero"

"strings"
)
Expand Down Expand Up @@ -78,6 +79,7 @@ func NewContentSpec(cfg config.Provider, logger *loggers.Logger, contentFs afero
ContentFs: contentFs,
Logger: logger,
})

if err != nil {
return nil, err
}
Expand Down
3 changes: 1 addition & 2 deletions helpers/general_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ import (

"github.com/spf13/viper"

"github.com/gohugoio/hugo/common/loggers"

qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/common/loggers"
"github.com/spf13/afero"
)

Expand Down
244 changes: 244 additions & 0 deletions hugolib/content_render_hooks_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
// Copyright 2019 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 requiredF 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"

func TestRenderHooks(t *testing.T) {
config := `
baseURL="https://example.org"
workingDir="/mywork"
`
b := newTestSitesBuilder(t).WithWorkingDir("/mywork").WithConfigFile("toml", config).Running()
b.WithTemplatesAdded("_default/single.html", `{{ .Content }}`)
b.WithTemplatesAdded("shortcodes/myshortcode1.html", `{{ partial "mypartial1" }}`)
b.WithTemplatesAdded("shortcodes/myshortcode2.html", `{{ partial "mypartial2" }}`)
b.WithTemplatesAdded("shortcodes/myshortcode3.html", `SHORT3|`)
b.WithTemplatesAdded("shortcodes/myshortcode4.html", `
<div class="foo">
{{ .Inner | markdownify }}
</div>
`)
b.WithTemplatesAdded("shortcodes/myshortcode5.html", `
Inner Inline: {{ .Inner | .Page.RenderString }}
Inner Block: {{ .Inner | .Page.RenderString (dict "display" "block" ) }}
`)

b.WithTemplatesAdded("shortcodes/myshortcode6.html", `.Render: {{ .Page.Render "myrender" }}`)
b.WithTemplatesAdded("partials/mypartial1.html", `PARTIAL1`)
b.WithTemplatesAdded("partials/mypartial2.html", `PARTIAL2 {{ partial "mypartial3.html" }}`)
b.WithTemplatesAdded("partials/mypartial3.html", `PARTIAL3`)
b.WithTemplatesAdded("partials/mypartial4.html", `PARTIAL4`)
b.WithTemplatesAdded("customview/myrender.html", `myrender: {{ .Title }}|P4: {{ partial "mypartial4" }}`)
b.WithTemplatesAdded("_default/_markup/render-link.html", `{{ with .Page }}{{ .Title }}{{ end }}|{{ .Destination | safeURL }}|Title: {{ .Title | safeHTML }}|Text: {{ .Text | safeHTML }}|END`)
b.WithTemplatesAdded("docs/_markup/render-link.html", `Link docs section: {{ .Text | safeHTML }}|END`)
b.WithTemplatesAdded("_default/_markup/render-image.html", `IMAGE: {{ .Page.Title }}||{{ .Destination | safeURL }}|Title: {{ .Title | safeHTML }}|Text: {{ .Text | safeHTML }}|END`)

b.WithContent("customview/p1.md", `---
title: Custom View
---
{{< myshortcode6 >}}
`, "blog/p1.md", `---
title: Cool Page
---
[First Link](https://www.google.com "Google's Homepage")
{{< myshortcode3 >}}
[Second Link](https://www.google.com "Google's Homepage")
Image:
![Drag Racing](/images/Dragster.jpg "image title")
`, "blog/p2.md", `---
title: Cool Page2
layout: mylayout
---
{{< myshortcode1 >}}
[Some Text](https://www.google.com "Google's Homepage")
`, "blog/p3.md", `---
title: Cool Page3
---
{{< myshortcode2 >}}
`, "docs/docs1.md", `---
title: Docs 1
---
[Docs 1](https://www.google.com "Google's Homepage")
`, "blog/p4.md", `---
title: Cool Page With Image
---
Image:
![Drag Racing](/images/Dragster.jpg "image title")
`, "blog/p5.md", `---
title: Cool Page With Markdownify
---
{{< myshortcode4 >}}
Inner Link: [Inner Link](https://www.google.com "Google's Homepage")
{{< /myshortcode4 >}}
`, "blog/p6.md", `---
title: With RenderString
---
{{< myshortcode5 >}}Inner Link: [Inner Link](https://www.gohugo.io "Hugo's Homepage"){{< /myshortcode5 >}}
`)
b.Build(BuildCfg{})
b.AssertFileContent("public/blog/p1/index.html", `
<p>Cool Page|https://www.google.com|Title: Google's Homepage|Text: First Link|END</p>
Text: Second
SHORT3|
<p>IMAGE: Cool Page||/images/Dragster.jpg|Title: image title|Text: Drag Racing|END</p>
`)

b.AssertFileContent("public/customview/p1/index.html", `.Render: myrender: Custom View|P4: PARTIAL4`)
b.AssertFileContent("public/blog/p2/index.html", `PARTIAL`)
b.AssertFileContent("public/blog/p3/index.html", `PARTIAL3`)
// We may add type template support later, keep this for then. b.AssertFileContent("public/docs/docs1/index.html", `Link docs section: Docs 1|END`)
b.AssertFileContent("public/blog/p4/index.html", `<p>IMAGE: Cool Page With Image||/images/Dragster.jpg|Title: image title|Text: Drag Racing|END</p>`)
// The regular markdownify func currently gets regular links.
b.AssertFileContent("public/blog/p5/index.html", "Inner Link: <a href=\"https://www.google.com\" title=\"Google's Homepage\">Inner Link</a>\n</div>")

b.AssertFileContent("public/blog/p6/index.html",
"Inner Inline: Inner Link: With RenderString|https://www.gohugo.io|Title: Hugo's Homepage|Text: Inner Link|END",
"Inner Block: <p>Inner Link: With RenderString|https://www.gohugo.io|Title: Hugo's Homepage|Text: Inner Link|END</p>",
)

b.EditFiles(
"layouts/_default/_markup/render-link.html", `EDITED: {{ .Destination | safeURL }}|`,
"layouts/_default/_markup/render-image.html", `IMAGE EDITED: {{ .Destination | safeURL }}|`,
"layouts/docs/_markup/render-link.html", `DOCS EDITED: {{ .Destination | safeURL }}|`,
"layouts/partials/mypartial1.html", `PARTIAL1_EDITED`,
"layouts/partials/mypartial3.html", `PARTIAL3_EDITED`,
"layouts/partials/mypartial4.html", `PARTIAL4_EDITED`,
"layouts/shortcodes/myshortcode3.html", `SHORT3_EDITED|`,
)

b.Build(BuildCfg{})
b.AssertFileContent("public/customview/p1/index.html", `.Render: myrender: Custom View|P4: PARTIAL4_EDITED`)
b.AssertFileContent("public/blog/p1/index.html", `<p>EDITED: https://www.google.com|</p>`, "SHORT3_EDITED|")
b.AssertFileContent("public/blog/p2/index.html", `PARTIAL1_EDITED`)
b.AssertFileContent("public/blog/p3/index.html", `PARTIAL3_EDITED`)
// We may add type template support later, keep this for then. b.AssertFileContent("public/docs/docs1/index.html", `DOCS EDITED: https://www.google.com|</p>`)
b.AssertFileContent("public/blog/p4/index.html", `IMAGE EDITED: /images/Dragster.jpg|`)
b.AssertFileContent("public/blog/p6/index.html", "<p>Inner Link: EDITED: https://www.gohugo.io|</p>")

}

func TestRenderHooksRSS(t *testing.T) {

b := newTestSitesBuilder(t)

b.WithTemplates("index.html", `
{{ $p := site.GetPage "p1.md" }}
P1: {{ $p.Content }}
`, "index.xml", `
{{ $p2 := site.GetPage "p2.md" }}
{{ $p3 := site.GetPage "p3.md" }}
P2: {{ $p2.Content }}
P3: {{ $p3.Content }}
`,
"_default/_markup/render-link.html", `html-link: {{ .Destination | safeURL }}|`,
"_default/_markup/render-link.rss.xml", `xml-link: {{ .Destination | safeURL }}|`,
)

b.WithContent("p1.md", `---
title: "p1"
---
P1. [I'm an inline-style link](https://www.gohugo.io)
`, "p2.md", `---
title: "p2"
---
P1. [I'm an inline-style link](https://www.bep.is)
`,
"p3.md", `---
title: "p2"
outputs: ["rss"]
---
P3. [I'm an inline-style link](https://www.example.org)
`,
)

b.Build(BuildCfg{})

b.AssertFileContent("public/index.html", "P1: <p>P1. html-link: https://www.gohugo.io|</p>")
b.AssertFileContent("public/index.xml", `
P2: <p>P1. xml-link: https://www.bep.is|</p>
P3: <p>P3. xml-link: https://www.example.org|</p>
`)

}

func TestRenderString(t *testing.T) {

b := newTestSitesBuilder(t)

b.WithTemplates("index.html", `
{{ $p := site.GetPage "p1.md" }}
{{ $optBlock := dict "display" "block" }}
{{ $optOrg := dict "markup" "org" }}
RSTART:{{ "**Bold Markdown**" | $p.RenderString }}:REND
RSTART:{{ "**Bold Block Markdown**" | $p.RenderString $optBlock }}:REND
RSTART:{{ "/italic org mode/" | $p.RenderString $optOrg }}:REND
`)

b.WithContent("p1.md", `---
title: "p1"
---
`,
)

b.Build(BuildCfg{})

b.AssertFileContent("public/index.html", `
RSTART:<strong>Bold Markdown</strong>:REND
RSTART:<p><strong>Bold Block Markdown</strong></p>
RSTART:<em>italic org mode</em>:REND
`)

}
Loading

0 comments on commit d3cf3f7

Please sign in to comment.