Skip to content

Commit

Permalink
Add render template hooks for headings
Browse files Browse the repository at this point in the history
This commit also

* Renames previous types to be non-specific. (e.g. hookedRenderer rather
  than linkRenderer)

Resolves #6713
  • Loading branch information
elihunter173 authored and bep committed May 15, 2020
1 parent 9919344 commit 423b8f2
Show file tree
Hide file tree
Showing 6 changed files with 202 additions and 63 deletions.
46 changes: 26 additions & 20 deletions hugolib/page.go
Original file line number Diff line number Diff line change
Expand Up @@ -375,48 +375,54 @@ func (ps *pageState) initCommonProviders(pp pagePaths) error {
return nil
}

func (p *pageState) createRenderHooks(f output.Format) (*hooks.Render, error) {

func (p *pageState) createRenderHooks(f output.Format) (*hooks.Renderers, error) {
layoutDescriptor := p.getLayoutDescriptor()
layoutDescriptor.RenderingHook = true
layoutDescriptor.LayoutOverride = false
layoutDescriptor.Layout = ""

var renderers hooks.Renderers

layoutDescriptor.Kind = "render-link"
linkTempl, linkTemplFound, err := p.s.Tmpl().LookupLayout(layoutDescriptor, f)
templ, templFound, err := p.s.Tmpl().LookupLayout(layoutDescriptor, f)
if err != nil {
return nil, err
}
if templFound {
renderers.LinkRenderer = hookRenderer{
templateHandler: p.s.Tmpl(),
Provider: templ.(tpl.Info),
templ: templ,
}
}

layoutDescriptor.Kind = "render-image"
imgTempl, imgTemplFound, err := p.s.Tmpl().LookupLayout(layoutDescriptor, f)
templ, templFound, err = p.s.Tmpl().LookupLayout(layoutDescriptor, f)
if err != nil {
return nil, err
}

var linkRenderer hooks.LinkRenderer
var imageRenderer hooks.LinkRenderer

if linkTemplFound {
linkRenderer = contentLinkRenderer{
if templFound {
renderers.ImageRenderer = hookRenderer{
templateHandler: p.s.Tmpl(),
Provider: linkTempl.(tpl.Info),
templ: linkTempl,
Provider: templ.(tpl.Info),
templ: templ,
}
}

if imgTemplFound {
imageRenderer = contentLinkRenderer{
layoutDescriptor.Kind = "render-heading"
templ, templFound, err = p.s.Tmpl().LookupLayout(layoutDescriptor, f)
if err != nil {
return nil, err
}
if templFound {
renderers.HeadingRenderer = hookRenderer{
templateHandler: p.s.Tmpl(),
Provider: imgTempl.(tpl.Info),
templ: imgTempl,
Provider: templ.(tpl.Info),
templ: templ,
}
}

return &hooks.Render{
LinkRenderer: linkRenderer,
ImageRenderer: imageRenderer,
}, nil
return &renderers, nil
}

func (p *pageState) getLayoutDescriptor() output.LayoutDescriptor {
Expand Down
2 changes: 1 addition & 1 deletion hugolib/page__per_output.go
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ type pageContentOutput struct {
placeholdersEnabledInit sync.Once

// May be nil.
renderHooks *hooks.Render
renderHooks *hooks.Renderers
// Set if there are more than one output format variant
renderHooksHaveVariants bool // TODO(bep) reimplement this in another way, consolidate with shortcodes

Expand Down
12 changes: 9 additions & 3 deletions hugolib/site.go
Original file line number Diff line number Diff line change
Expand Up @@ -1650,14 +1650,20 @@ var infoOnMissingLayout = map[string]bool{
"404": true,
}

type contentLinkRenderer struct {
// hookRenderer is the canonical implementation of all hooks.ITEMRenderer,
// where ITEM is the thing being hooked.
type hookRenderer struct {
templateHandler tpl.TemplateHandler
identity.Provider
templ tpl.Template
}

func (r contentLinkRenderer) Render(w io.Writer, ctx hooks.LinkContext) error {
return r.templateHandler.Execute(r.templ, w, ctx)
func (hr hookRenderer) RenderLink(w io.Writer, ctx hooks.LinkContext) error {
return hr.templateHandler.Execute(hr.templ, w, ctx)
}

func (hr hookRenderer) RenderHeading(w io.Writer, ctx hooks.HeadingContext) error {
return hr.templateHandler.Execute(hr.templ, w, ctx)
}

func (s *Site) renderForTemplate(name, outputFormat string, d interface{}, w io.Writer, templ tpl.Template) (err error) {
Expand Down
2 changes: 1 addition & 1 deletion markup/converter/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ type DocumentContext struct {
type RenderContext struct {
Src []byte
RenderTOC bool
RenderHooks *hooks.Render
RenderHooks *hooks.Renderers
}

var (
Expand Down
47 changes: 37 additions & 10 deletions markup/converter/hooks/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,41 @@ type LinkContext interface {
PlainText() string
}

type Render struct {
LinkRenderer LinkRenderer
ImageRenderer LinkRenderer
type LinkRenderer interface {
RenderLink(w io.Writer, ctx LinkContext) error
identity.Provider
}

// HeadingContext contains accessors to all attributes that a HeadingRenderer
// can use to render a heading.
type HeadingContext interface {
// Page is the page containing the heading.
Page() interface{}
// Level is the level of the header (i.e. 1 for top-level, 2 for sub-level, etc.).
Level() int
// Anchor is the HTML id assigned to the heading.
Anchor() string
// Text is the rendered (HTML) heading text, excluding the heading marker.
Text() string
// PlainText is the unrendered version of Text.
PlainText() string
}

// HeadingRenderer describes a uniquely identifiable rendering hook.
type HeadingRenderer interface {
// Render writes the renderered content to w using the data in w.
RenderHeading(w io.Writer, ctx HeadingContext) error
identity.Provider
}

func (r *Render) Eq(other interface{}) bool {
ro, ok := other.(*Render)
type Renderers struct {
LinkRenderer LinkRenderer
ImageRenderer LinkRenderer
HeadingRenderer HeadingRenderer
}

func (r *Renderers) Eq(other interface{}) bool {
ro, ok := other.(*Renderers)
if !ok {
return false
}
Expand All @@ -49,10 +77,9 @@ func (r *Render) Eq(other interface{}) bool {
return false
}

return true
}
if r.HeadingRenderer.GetIdentity() != ro.HeadingRenderer.GetIdentity() {
return false
}

type LinkRenderer interface {
Render(w io.Writer, ctx LinkContext) error
identity.Provider
return true
}
Loading

0 comments on commit 423b8f2

Please sign in to comment.