mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-29 23:53:32 -05:00
Move template library into it's own package (tpl). No longer dependent on hugolib. Can be used externally.
This commit is contained in:
parent
92a3372a3f
commit
73f203ad86
8 changed files with 151 additions and 113 deletions
|
@ -17,10 +17,6 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/hugo/helpers"
|
|
||||||
"github.com/spf13/hugo/parser"
|
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
@ -29,8 +25,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cast"
|
"github.com/spf13/cast"
|
||||||
|
"github.com/spf13/hugo/helpers"
|
||||||
"github.com/spf13/hugo/hugofs"
|
"github.com/spf13/hugo/hugofs"
|
||||||
|
"github.com/spf13/hugo/parser"
|
||||||
"github.com/spf13/hugo/source"
|
"github.com/spf13/hugo/source"
|
||||||
|
"github.com/spf13/hugo/tpl"
|
||||||
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Page struct {
|
type Page struct {
|
||||||
|
@ -44,7 +45,7 @@ type Page struct {
|
||||||
Truncated bool
|
Truncated bool
|
||||||
Draft bool
|
Draft bool
|
||||||
PublishDate time.Time
|
PublishDate time.Time
|
||||||
Tmpl Template
|
Tmpl tpl.Template
|
||||||
Markup string
|
Markup string
|
||||||
|
|
||||||
extension string
|
extension string
|
||||||
|
@ -528,7 +529,7 @@ func (p *Page) Render(layout ...string) template.HTML {
|
||||||
curLayout = layout[0]
|
curLayout = layout[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExecuteTemplateToHTML(p, p.Layout(curLayout)...)
|
return tpl.ExecuteTemplateToHTML(p, p.Layout(curLayout)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (page *Page) guessMarkupType() string {
|
func (page *Page) guessMarkupType() string {
|
||||||
|
@ -629,7 +630,7 @@ func (page *Page) SaveSource() error {
|
||||||
return page.SaveSourceAs(page.FullFilePath())
|
return page.SaveSourceAs(page.FullFilePath())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Page) ProcessShortcodes(t Template) {
|
func (p *Page) ProcessShortcodes(t tpl.Template) {
|
||||||
|
|
||||||
// these short codes aren't used until after Page render,
|
// these short codes aren't used until after Page render,
|
||||||
// but processed here to avoid coupling
|
// but processed here to avoid coupling
|
||||||
|
|
|
@ -16,14 +16,16 @@ package hugolib
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/hugo/helpers"
|
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
|
||||||
"html/template"
|
"html/template"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/spf13/hugo/helpers"
|
||||||
|
"github.com/spf13/hugo/tpl"
|
||||||
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ShortcodeFunc func([]string) string
|
type ShortcodeFunc func([]string) string
|
||||||
|
@ -117,7 +119,7 @@ func (sc shortcode) String() string {
|
||||||
|
|
||||||
// all in one go: extract, render and replace
|
// all in one go: extract, render and replace
|
||||||
// only used for testing
|
// only used for testing
|
||||||
func ShortcodesHandle(stringToParse string, page *Page, t Template) string {
|
func ShortcodesHandle(stringToParse string, page *Page, t tpl.Template) string {
|
||||||
|
|
||||||
tmpContent, tmpShortcodes := extractAndRenderShortcodes(stringToParse, page, t)
|
tmpContent, tmpShortcodes := extractAndRenderShortcodes(stringToParse, page, t)
|
||||||
|
|
||||||
|
@ -154,7 +156,7 @@ func createShortcodePlaceholder(id int) string {
|
||||||
return fmt.Sprintf("<div>%s-%d</div>", shortcodePlaceholderPrefix, id)
|
return fmt.Sprintf("<div>%s-%d</div>", shortcodePlaceholderPrefix, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderShortcodes(sc shortcode, p *Page, t Template) string {
|
func renderShortcodes(sc shortcode, p *Page, t tpl.Template) string {
|
||||||
|
|
||||||
tokenizedRenderedShortcodes := make(map[string](string))
|
tokenizedRenderedShortcodes := make(map[string](string))
|
||||||
startCount := 0
|
startCount := 0
|
||||||
|
@ -169,7 +171,7 @@ func renderShortcodes(sc shortcode, p *Page, t Template) string {
|
||||||
return shortcodes
|
return shortcodes
|
||||||
}
|
}
|
||||||
|
|
||||||
func renderShortcode(sc shortcode, tokenizedShortcodes map[string](string), cnt int, p *Page, t Template) string {
|
func renderShortcode(sc shortcode, tokenizedShortcodes map[string](string), cnt int, p *Page, t tpl.Template) string {
|
||||||
var data = &ShortcodeWithPage{Params: sc.params, Page: p}
|
var data = &ShortcodeWithPage{Params: sc.params, Page: p}
|
||||||
tmpl := GetTemplate(sc.name, t)
|
tmpl := GetTemplate(sc.name, t)
|
||||||
|
|
||||||
|
@ -209,7 +211,7 @@ func renderShortcode(sc shortcode, tokenizedShortcodes map[string](string), cnt
|
||||||
return ShortcodeRender(tmpl, data)
|
return ShortcodeRender(tmpl, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractAndRenderShortcodes(stringToParse string, p *Page, t Template) (string, map[string]string) {
|
func extractAndRenderShortcodes(stringToParse string, p *Page, t tpl.Template) (string, map[string]string) {
|
||||||
|
|
||||||
content, shortcodes, err := extractShortcodes(stringToParse, p, t)
|
content, shortcodes, err := extractShortcodes(stringToParse, p, t)
|
||||||
renderedShortcodes := make(map[string]string)
|
renderedShortcodes := make(map[string]string)
|
||||||
|
@ -235,7 +237,7 @@ func extractAndRenderShortcodes(stringToParse string, p *Page, t Template) (stri
|
||||||
// pageTokens state:
|
// pageTokens state:
|
||||||
// - before: positioned just before the shortcode start
|
// - before: positioned just before the shortcode start
|
||||||
// - after: shortcode(s) consumed (plural when they are nested)
|
// - after: shortcode(s) consumed (plural when they are nested)
|
||||||
func extractShortcode(pt *pageTokens, p *Page, t Template) (shortcode, error) {
|
func extractShortcode(pt *pageTokens, p *Page, t tpl.Template) (shortcode, error) {
|
||||||
sc := shortcode{}
|
sc := shortcode{}
|
||||||
var isInner = false
|
var isInner = false
|
||||||
|
|
||||||
|
@ -334,7 +336,7 @@ Loop:
|
||||||
return sc, nil
|
return sc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractShortcodes(stringToParse string, p *Page, t Template) (string, map[string]shortcode, error) {
|
func extractShortcodes(stringToParse string, p *Page, t tpl.Template) (string, map[string]shortcode, error) {
|
||||||
|
|
||||||
shortCodes := make(map[string]shortcode)
|
shortCodes := make(map[string]shortcode)
|
||||||
|
|
||||||
|
@ -452,7 +454,7 @@ func replaceShortcodeTokens(source []byte, prefix string, numReplacements int, w
|
||||||
return buff[0:width], nil
|
return buff[0:width], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetTemplate(name string, t Template) *template.Template {
|
func GetTemplate(name string, t tpl.Template) *template.Template {
|
||||||
if x := t.Lookup("shortcodes/" + name + ".html"); x != nil {
|
if x := t.Lookup("shortcodes/" + name + ".html"); x != nil {
|
||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,20 +2,22 @@ package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/hugo/helpers"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/spf13/hugo/helpers"
|
||||||
|
"github.com/spf13/hugo/tpl"
|
||||||
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
func pageFromString(in, filename string) (*Page, error) {
|
func pageFromString(in, filename string) (*Page, error) {
|
||||||
return NewPageFrom(strings.NewReader(in), filename)
|
return NewPageFrom(strings.NewReader(in), filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckShortCodeMatch(t *testing.T, input, expected string, template Template) {
|
func CheckShortCodeMatch(t *testing.T, input, expected string, template tpl.Template) {
|
||||||
|
|
||||||
p, _ := pageFromString(SIMPLE_PAGE, "simple.md")
|
p, _ := pageFromString(SIMPLE_PAGE, "simple.md")
|
||||||
output := ShortcodesHandle(input, p, template)
|
output := ShortcodesHandle(input, p, template)
|
||||||
|
@ -26,13 +28,13 @@ func CheckShortCodeMatch(t *testing.T, input, expected string, template Template
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNonSC(t *testing.T) {
|
func TestNonSC(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
// notice the syntax diff from 0.12, now comment delims must be added
|
// notice the syntax diff from 0.12, now comment delims must be added
|
||||||
CheckShortCodeMatch(t, "{{%/* movie 47238zzb */%}}", "{{% movie 47238zzb %}}", tem)
|
CheckShortCodeMatch(t, "{{%/* movie 47238zzb */%}}", "{{% movie 47238zzb %}}", tem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPositionalParamSC(t *testing.T) {
|
func TestPositionalParamSC(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
tem.AddInternalShortcode("video.html", `Playing Video {{ .Get 0 }}`)
|
tem.AddInternalShortcode("video.html", `Playing Video {{ .Get 0 }}`)
|
||||||
|
|
||||||
CheckShortCodeMatch(t, "{{< video 47238zzb >}}", "Playing Video 47238zzb", tem)
|
CheckShortCodeMatch(t, "{{< video 47238zzb >}}", "Playing Video 47238zzb", tem)
|
||||||
|
@ -43,7 +45,7 @@ func TestPositionalParamSC(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNamedParamSC(t *testing.T) {
|
func TestNamedParamSC(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
tem.AddInternalShortcode("img.html", `<img{{ with .Get "src" }} src="{{.}}"{{end}}{{with .Get "class"}} class="{{.}}"{{end}}>`)
|
tem.AddInternalShortcode("img.html", `<img{{ with .Get "src" }} src="{{.}}"{{end}}{{with .Get "class"}} class="{{.}}"{{end}}>`)
|
||||||
|
|
||||||
CheckShortCodeMatch(t, `{{< img src="one" >}}`, `<img src="one">`, tem)
|
CheckShortCodeMatch(t, `{{< img src="one" >}}`, `<img src="one">`, tem)
|
||||||
|
@ -55,7 +57,7 @@ func TestNamedParamSC(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInnerSC(t *testing.T) {
|
func TestInnerSC(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
tem.AddInternalShortcode("inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`)
|
tem.AddInternalShortcode("inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`)
|
||||||
|
|
||||||
CheckShortCodeMatch(t, `{{< inside class="aspen" >}}`, `<div class="aspen"></div>`, tem)
|
CheckShortCodeMatch(t, `{{< inside class="aspen" >}}`, `<div class="aspen"></div>`, tem)
|
||||||
|
@ -64,7 +66,7 @@ func TestInnerSC(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInnerSCWithMarkdown(t *testing.T) {
|
func TestInnerSCWithMarkdown(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
tem.AddInternalShortcode("inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`)
|
tem.AddInternalShortcode("inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`)
|
||||||
|
|
||||||
CheckShortCodeMatch(t, `{{% inside %}}
|
CheckShortCodeMatch(t, `{{% inside %}}
|
||||||
|
@ -76,7 +78,7 @@ func TestInnerSCWithMarkdown(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInnerSCWithAndWithoutMarkdown(t *testing.T) {
|
func TestInnerSCWithAndWithoutMarkdown(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
tem.AddInternalShortcode("inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`)
|
tem.AddInternalShortcode("inside.html", `<div{{with .Get "class"}} class="{{.}}"{{end}}>{{ .Inner }}</div>`)
|
||||||
|
|
||||||
CheckShortCodeMatch(t, `{{% inside %}}
|
CheckShortCodeMatch(t, `{{% inside %}}
|
||||||
|
@ -98,14 +100,14 @@ This is **plain** text.
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEmbeddedSC(t *testing.T) {
|
func TestEmbeddedSC(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
CheckShortCodeMatch(t, "{{% test %}}", "This is a simple Test", tem)
|
CheckShortCodeMatch(t, "{{% test %}}", "This is a simple Test", tem)
|
||||||
CheckShortCodeMatch(t, `{{% figure src="/found/here" class="bananas orange" %}}`, "\n<figure class=\"bananas orange\">\n \n <img src=\"/found/here\" />\n \n \n</figure>\n", tem)
|
CheckShortCodeMatch(t, `{{% figure src="/found/here" class="bananas orange" %}}`, "\n<figure class=\"bananas orange\">\n \n <img src=\"/found/here\" />\n \n \n</figure>\n", tem)
|
||||||
CheckShortCodeMatch(t, `{{% figure src="/found/here" class="bananas orange" caption="This is a caption" %}}`, "\n<figure class=\"bananas orange\">\n \n <img src=\"/found/here\" alt=\"This is a caption\" />\n \n \n <figcaption>\n <p>\n This is a caption\n \n \n \n </p> \n </figcaption>\n \n</figure>\n", tem)
|
CheckShortCodeMatch(t, `{{% figure src="/found/here" class="bananas orange" caption="This is a caption" %}}`, "\n<figure class=\"bananas orange\">\n \n <img src=\"/found/here\" alt=\"This is a caption\" />\n \n \n <figcaption>\n <p>\n This is a caption\n \n \n \n </p> \n </figcaption>\n \n</figure>\n", tem)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNestedSC(t *testing.T) {
|
func TestNestedSC(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
tem.AddInternalShortcode("scn1.html", `<div>Outer, inner is {{ .Inner }}</div>`)
|
tem.AddInternalShortcode("scn1.html", `<div>Outer, inner is {{ .Inner }}</div>`)
|
||||||
tem.AddInternalShortcode("scn2.html", `<div>SC2</div>`)
|
tem.AddInternalShortcode("scn2.html", `<div>SC2</div>`)
|
||||||
|
|
||||||
|
@ -113,7 +115,7 @@ func TestNestedSC(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNestedComplexSC(t *testing.T) {
|
func TestNestedComplexSC(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
tem.AddInternalShortcode("row.html", `-row-{{ .Inner}}-rowStop-`)
|
tem.AddInternalShortcode("row.html", `-row-{{ .Inner}}-rowStop-`)
|
||||||
tem.AddInternalShortcode("column.html", `-col-{{.Inner }}-colStop-`)
|
tem.AddInternalShortcode("column.html", `-col-{{.Inner }}-colStop-`)
|
||||||
tem.AddInternalShortcode("aside.html", `-aside-{{ .Inner }}-asideStop-`)
|
tem.AddInternalShortcode("aside.html", `-aside-{{ .Inner }}-asideStop-`)
|
||||||
|
@ -127,7 +129,7 @@ func TestNestedComplexSC(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFigureImgWidth(t *testing.T) {
|
func TestFigureImgWidth(t *testing.T) {
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
CheckShortCodeMatch(t, `{{% figure src="/found/here" class="bananas orange" alt="apple" width="100px" %}}`, "\n<figure class=\"bananas orange\">\n \n <img src=\"/found/here\" alt=\"apple\" width=\"100px\" />\n \n \n</figure>\n", tem)
|
CheckShortCodeMatch(t, `{{% figure src="/found/here" class="bananas orange" alt="apple" width="100px" %}}`, "\n<figure class=\"bananas orange\">\n \n <img src=\"/found/here\" alt=\"apple\" width=\"100px\" />\n \n \n</figure>\n", tem)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +140,7 @@ func TestHighlight(t *testing.T) {
|
||||||
defer viper.Set("PygmentsStyle", viper.Get("PygmentsStyle"))
|
defer viper.Set("PygmentsStyle", viper.Get("PygmentsStyle"))
|
||||||
viper.Set("PygmentsStyle", "bw")
|
viper.Set("PygmentsStyle", "bw")
|
||||||
|
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
|
|
||||||
code := `
|
code := `
|
||||||
{{< highlight java >}}
|
{{< highlight java >}}
|
||||||
|
@ -196,7 +198,7 @@ func TestExtractShortcodes(t *testing.T) {
|
||||||
} {
|
} {
|
||||||
|
|
||||||
p, _ := pageFromString(SIMPLE_PAGE, "simple.md")
|
p, _ := pageFromString(SIMPLE_PAGE, "simple.md")
|
||||||
tem := NewTemplate()
|
tem := tpl.New()
|
||||||
tem.AddInternalShortcode("tag.html", `tag`)
|
tem.AddInternalShortcode("tag.html", `tag`)
|
||||||
tem.AddInternalShortcode("sc1.html", `sc1`)
|
tem.AddInternalShortcode("sc1.html", `sc1`)
|
||||||
tem.AddInternalShortcode("sc2.html", `sc2`)
|
tem.AddInternalShortcode("sc2.html", `sc2`)
|
||||||
|
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"github.com/spf13/hugo/hugofs"
|
"github.com/spf13/hugo/hugofs"
|
||||||
"github.com/spf13/hugo/source"
|
"github.com/spf13/hugo/source"
|
||||||
"github.com/spf13/hugo/target"
|
"github.com/spf13/hugo/target"
|
||||||
|
"github.com/spf13/hugo/tpl"
|
||||||
"github.com/spf13/hugo/transform"
|
"github.com/spf13/hugo/transform"
|
||||||
jww "github.com/spf13/jwalterweatherman"
|
jww "github.com/spf13/jwalterweatherman"
|
||||||
"github.com/spf13/nitro"
|
"github.com/spf13/nitro"
|
||||||
|
@ -61,7 +62,7 @@ var DefaultTimer *nitro.B
|
||||||
type Site struct {
|
type Site struct {
|
||||||
Pages Pages
|
Pages Pages
|
||||||
Files []*source.File
|
Files []*source.File
|
||||||
Tmpl Template
|
Tmpl tpl.Template
|
||||||
Taxonomies TaxonomyList
|
Taxonomies TaxonomyList
|
||||||
Source source.Input
|
Source source.Input
|
||||||
Sections Taxonomy
|
Sections Taxonomy
|
||||||
|
@ -166,7 +167,7 @@ func (s *Site) Analyze() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) prepTemplates() {
|
func (s *Site) prepTemplates() {
|
||||||
s.Tmpl = NewTemplate()
|
s.Tmpl = tpl.T()
|
||||||
s.Tmpl.LoadTemplates(s.absLayoutDir())
|
s.Tmpl.LoadTemplates(s.absLayoutDir())
|
||||||
if s.hasTheme() {
|
if s.hasTheme() {
|
||||||
s.Tmpl.LoadTemplatesWithPrefix(s.absThemeDir()+"/layouts", "theme")
|
s.Tmpl.LoadTemplatesWithPrefix(s.absThemeDir()+"/layouts", "theme")
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/spf13/hugo/hugofs"
|
"github.com/spf13/hugo/hugofs"
|
||||||
"github.com/spf13/hugo/source"
|
"github.com/spf13/hugo/source"
|
||||||
"github.com/spf13/hugo/target"
|
"github.com/spf13/hugo/target"
|
||||||
|
"github.com/spf13/hugo/tpl"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,6 +47,14 @@ more text
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func templatePrep(s *Site) {
|
||||||
|
s.Tmpl = tpl.New()
|
||||||
|
s.Tmpl.LoadTemplates(s.absLayoutDir())
|
||||||
|
if s.hasTheme() {
|
||||||
|
s.Tmpl.LoadTemplatesWithPrefix(s.absThemeDir()+"/layouts", "theme")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func pageMust(p *Page, err error) *Page {
|
func pageMust(p *Page, err error) *Page {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -57,7 +66,7 @@ func TestDegenerateRenderThingMissingTemplate(t *testing.T) {
|
||||||
p, _ := NewPageFrom(strings.NewReader(PAGE_SIMPLE_TITLE), "content/a/file.md")
|
p, _ := NewPageFrom(strings.NewReader(PAGE_SIMPLE_TITLE), "content/a/file.md")
|
||||||
p.Convert()
|
p.Convert()
|
||||||
s := new(Site)
|
s := new(Site)
|
||||||
s.prepTemplates()
|
templatePrep(s)
|
||||||
err := s.renderThing(p, "foobar", nil)
|
err := s.renderThing(p, "foobar", nil)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Errorf("Expected err to be returned when missing the template.")
|
t.Errorf("Expected err to be returned when missing the template.")
|
||||||
|
@ -66,7 +75,7 @@ func TestDegenerateRenderThingMissingTemplate(t *testing.T) {
|
||||||
|
|
||||||
func TestAddInvalidTemplate(t *testing.T) {
|
func TestAddInvalidTemplate(t *testing.T) {
|
||||||
s := new(Site)
|
s := new(Site)
|
||||||
s.prepTemplates()
|
templatePrep(s)
|
||||||
err := s.addTemplate("missing", TEMPLATE_MISSING_FUNC)
|
err := s.addTemplate("missing", TEMPLATE_MISSING_FUNC)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatalf("Expecting the template to return an error")
|
t.Fatalf("Expecting the template to return an error")
|
||||||
|
@ -108,7 +117,7 @@ func TestRenderThing(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s := new(Site)
|
s := new(Site)
|
||||||
s.prepTemplates()
|
templatePrep(s)
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
p, err := NewPageFrom(strings.NewReader(test.content), "content/a/file.md")
|
p, err := NewPageFrom(strings.NewReader(test.content), "content/a/file.md")
|
||||||
|
@ -154,7 +163,7 @@ func TestRenderThingOrDefault(t *testing.T) {
|
||||||
|
|
||||||
hugofs.DestinationFS = new(afero.MemMapFs)
|
hugofs.DestinationFS = new(afero.MemMapFs)
|
||||||
s := &Site{}
|
s := &Site{}
|
||||||
s.prepTemplates()
|
templatePrep(s)
|
||||||
|
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
p, err := NewPageFrom(strings.NewReader(PAGE_SIMPLE_TITLE), "content/a/file.md")
|
p, err := NewPageFrom(strings.NewReader(PAGE_SIMPLE_TITLE), "content/a/file.md")
|
||||||
|
@ -306,7 +315,7 @@ func TestSkipRender(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s.initializeSiteInfo()
|
s.initializeSiteInfo()
|
||||||
s.prepTemplates()
|
templatePrep(s)
|
||||||
|
|
||||||
must(s.addTemplate("_default/single.html", "{{.Content}}"))
|
must(s.addTemplate("_default/single.html", "{{.Content}}"))
|
||||||
must(s.addTemplate("head", "<head><script src=\"script.js\"></script></head>"))
|
must(s.addTemplate("head", "<head><script src=\"script.js\"></script></head>"))
|
||||||
|
@ -366,7 +375,7 @@ func TestAbsUrlify(t *testing.T) {
|
||||||
}
|
}
|
||||||
t.Logf("Rendering with BaseUrl %q and CanonifyUrls set %v", viper.GetString("baseUrl"), canonify)
|
t.Logf("Rendering with BaseUrl %q and CanonifyUrls set %v", viper.GetString("baseUrl"), canonify)
|
||||||
s.initializeSiteInfo()
|
s.initializeSiteInfo()
|
||||||
s.prepTemplates()
|
templatePrep(s)
|
||||||
must(s.addTemplate("blue/single.html", TEMPLATE_WITH_URL_ABS))
|
must(s.addTemplate("blue/single.html", TEMPLATE_WITH_URL_ABS))
|
||||||
|
|
||||||
if err := s.CreatePages(); err != nil {
|
if err := s.CreatePages(); err != nil {
|
||||||
|
|
|
@ -1,4 +1,17 @@
|
||||||
package hugolib
|
// Copyright © 2013-14 Steve Francia <spf@spf13.com>.
|
||||||
|
//
|
||||||
|
// Licensed under the Simple Public 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://opensource.org/licenses/Simple-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 tpl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
@ -20,6 +33,82 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var localTemplates *template.Template
|
var localTemplates *template.Template
|
||||||
|
var tmpl Template
|
||||||
|
|
||||||
|
type Template interface {
|
||||||
|
ExecuteTemplate(wr io.Writer, name string, data interface{}) error
|
||||||
|
Lookup(name string) *template.Template
|
||||||
|
Templates() []*template.Template
|
||||||
|
New(name string) *template.Template
|
||||||
|
LoadTemplates(absPath string)
|
||||||
|
LoadTemplatesWithPrefix(absPath, prefix string)
|
||||||
|
AddTemplate(name, tpl string) error
|
||||||
|
AddInternalTemplate(prefix, name, tpl string) error
|
||||||
|
AddInternalShortcode(name, tpl string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type templateErr struct {
|
||||||
|
name string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
type GoHtmlTemplate struct {
|
||||||
|
template.Template
|
||||||
|
errors []*templateErr
|
||||||
|
}
|
||||||
|
|
||||||
|
// The "Global" Template System
|
||||||
|
func T() Template {
|
||||||
|
if tmpl == nil {
|
||||||
|
tmpl = New()
|
||||||
|
}
|
||||||
|
|
||||||
|
return tmpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a new Hugo Template System
|
||||||
|
// With all the additional features, templates & functions
|
||||||
|
func New() Template {
|
||||||
|
var templates = &GoHtmlTemplate{
|
||||||
|
Template: *template.New(""),
|
||||||
|
errors: make([]*templateErr, 0),
|
||||||
|
}
|
||||||
|
|
||||||
|
localTemplates = &templates.Template
|
||||||
|
|
||||||
|
funcMap := template.FuncMap{
|
||||||
|
"urlize": helpers.Urlize,
|
||||||
|
"sanitizeurl": helpers.SanitizeUrl,
|
||||||
|
"eq": Eq,
|
||||||
|
"ne": Ne,
|
||||||
|
"gt": Gt,
|
||||||
|
"ge": Ge,
|
||||||
|
"lt": Lt,
|
||||||
|
"le": Le,
|
||||||
|
"in": In,
|
||||||
|
"intersect": Intersect,
|
||||||
|
"isset": IsSet,
|
||||||
|
"echoParam": ReturnWhenSet,
|
||||||
|
"safeHtml": SafeHtml,
|
||||||
|
"first": First,
|
||||||
|
"where": Where,
|
||||||
|
"highlight": Highlight,
|
||||||
|
"add": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
|
||||||
|
"sub": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },
|
||||||
|
"div": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },
|
||||||
|
"mod": Mod,
|
||||||
|
"mul": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },
|
||||||
|
"modBool": ModBool,
|
||||||
|
"lower": func(a string) string { return strings.ToLower(a) },
|
||||||
|
"upper": func(a string) string { return strings.ToUpper(a) },
|
||||||
|
"title": func(a string) string { return strings.Title(a) },
|
||||||
|
"partial": Partial,
|
||||||
|
}
|
||||||
|
|
||||||
|
templates.Funcs(funcMap)
|
||||||
|
templates.LoadEmbedded()
|
||||||
|
return templates
|
||||||
|
}
|
||||||
|
|
||||||
func Eq(x, y interface{}) bool {
|
func Eq(x, y interface{}) bool {
|
||||||
return reflect.DeepEqual(x, y)
|
return reflect.DeepEqual(x, y)
|
||||||
|
@ -484,71 +573,6 @@ func ModBool(a, b interface{}) (bool, error) {
|
||||||
return res == int64(0), nil
|
return res == int64(0), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Template interface {
|
|
||||||
ExecuteTemplate(wr io.Writer, name string, data interface{}) error
|
|
||||||
Lookup(name string) *template.Template
|
|
||||||
Templates() []*template.Template
|
|
||||||
New(name string) *template.Template
|
|
||||||
LoadTemplates(absPath string)
|
|
||||||
LoadTemplatesWithPrefix(absPath, prefix string)
|
|
||||||
AddTemplate(name, tpl string) error
|
|
||||||
AddInternalTemplate(prefix, name, tpl string) error
|
|
||||||
AddInternalShortcode(name, tpl string) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type templateErr struct {
|
|
||||||
name string
|
|
||||||
err error
|
|
||||||
}
|
|
||||||
|
|
||||||
type GoHtmlTemplate struct {
|
|
||||||
template.Template
|
|
||||||
errors []*templateErr
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewTemplate() Template {
|
|
||||||
var templates = &GoHtmlTemplate{
|
|
||||||
Template: *template.New(""),
|
|
||||||
errors: make([]*templateErr, 0),
|
|
||||||
}
|
|
||||||
|
|
||||||
localTemplates = &templates.Template
|
|
||||||
|
|
||||||
funcMap := template.FuncMap{
|
|
||||||
"urlize": helpers.Urlize,
|
|
||||||
"sanitizeurl": helpers.SanitizeUrl,
|
|
||||||
"eq": Eq,
|
|
||||||
"ne": Ne,
|
|
||||||
"gt": Gt,
|
|
||||||
"ge": Ge,
|
|
||||||
"lt": Lt,
|
|
||||||
"le": Le,
|
|
||||||
"in": In,
|
|
||||||
"intersect": Intersect,
|
|
||||||
"isset": IsSet,
|
|
||||||
"echoParam": ReturnWhenSet,
|
|
||||||
"safeHtml": SafeHtml,
|
|
||||||
"first": First,
|
|
||||||
"where": Where,
|
|
||||||
"highlight": Highlight,
|
|
||||||
"add": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
|
|
||||||
"sub": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },
|
|
||||||
"div": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },
|
|
||||||
"mod": Mod,
|
|
||||||
"mul": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },
|
|
||||||
"modBool": ModBool,
|
|
||||||
"lower": func(a string) string { return strings.ToLower(a) },
|
|
||||||
"upper": func(a string) string { return strings.ToUpper(a) },
|
|
||||||
"title": func(a string) string { return strings.Title(a) },
|
|
||||||
"partial": Partial,
|
|
||||||
}
|
|
||||||
|
|
||||||
templates.Funcs(funcMap)
|
|
||||||
|
|
||||||
templates.LoadEmbedded()
|
|
||||||
return templates
|
|
||||||
}
|
|
||||||
|
|
||||||
func Partial(name string, context_list ...interface{}) template.HTML {
|
func Partial(name string, context_list ...interface{}) template.HTML {
|
||||||
if strings.HasPrefix("partials/", name) {
|
if strings.HasPrefix("partials/", name) {
|
||||||
name = name[8:]
|
name = name[8:]
|
|
@ -11,7 +11,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package hugolib
|
package tpl
|
||||||
|
|
||||||
type Tmpl struct {
|
type Tmpl struct {
|
||||||
Name string
|
Name string
|
|
@ -1,7 +1,6 @@
|
||||||
package hugolib
|
package tpl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/spf13/hugo/source"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
@ -310,9 +309,9 @@ type TstX struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWhere(t *testing.T) {
|
func TestWhere(t *testing.T) {
|
||||||
|
// TODO(spf): Put these page tests back in
|
||||||
page1 := &Page{contentType: "v", Source: Source{File: *source.NewFile("/x/y/z/source.md")}}
|
//page1 := &Page{contentType: "v", Source: Source{File: *source.NewFile("/x/y/z/source.md")}}
|
||||||
page2 := &Page{contentType: "w", Source: Source{File: *source.NewFile("/y/z/a/source.md")}}
|
//page2 := &Page{contentType: "w", Source: Source{File: *source.NewFile("/y/z/a/source.md")}}
|
||||||
|
|
||||||
for i, this := range []struct {
|
for i, this := range []struct {
|
||||||
sequence interface{}
|
sequence interface{}
|
||||||
|
@ -327,8 +326,8 @@ func TestWhere(t *testing.T) {
|
||||||
{[]*TstX{&TstX{"a", "b"}, &TstX{"c", "d"}, &TstX{"e", "f"}}, "B", "f", []*TstX{&TstX{"e", "f"}}},
|
{[]*TstX{&TstX{"a", "b"}, &TstX{"c", "d"}, &TstX{"e", "f"}}, "B", "f", []*TstX{&TstX{"e", "f"}}},
|
||||||
{[]*TstX{&TstX{"a", "b"}, &TstX{"c", "d"}, &TstX{"e", "c"}}, "TstRp", "rc", []*TstX{&TstX{"c", "d"}}},
|
{[]*TstX{&TstX{"a", "b"}, &TstX{"c", "d"}, &TstX{"e", "c"}}, "TstRp", "rc", []*TstX{&TstX{"c", "d"}}},
|
||||||
{[]TstX{TstX{"a", "b"}, TstX{"c", "d"}, TstX{"e", "c"}}, "TstRv", "rc", []TstX{TstX{"e", "c"}}},
|
{[]TstX{TstX{"a", "b"}, TstX{"c", "d"}, TstX{"e", "c"}}, "TstRv", "rc", []TstX{TstX{"e", "c"}}},
|
||||||
{[]*Page{page1, page2}, "Type", "v", []*Page{page1}},
|
//{[]*Page{page1, page2}, "Type", "v", []*Page{page1}},
|
||||||
{[]*Page{page1, page2}, "Section", "y", []*Page{page2}},
|
//{[]*Page{page1, page2}, "Section", "y", []*Page{page2}},
|
||||||
} {
|
} {
|
||||||
results, err := Where(this.sequence, this.key, this.match)
|
results, err := Where(this.sequence, this.key, this.match)
|
||||||
if err != nil {
|
if err != nil {
|
Loading…
Reference in a new issue