mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Add support for amber files
If a layout file ends with .amber it will interpreted as a Amber file Signed-off-by: Noah Campbell <noahcampbell@gmail.com>
This commit is contained in:
parent
ee5865f239
commit
ba82a20321
6 changed files with 171 additions and 108 deletions
|
@ -21,7 +21,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/BurntSushi/toml"
|
"github.com/BurntSushi/toml"
|
||||||
"github.com/theplant/blackfriday"
|
"github.com/theplant/blackfriday"
|
||||||
"html/template"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"launchpad.net/goyaml"
|
"launchpad.net/goyaml"
|
||||||
|
@ -46,7 +45,7 @@ type Page struct {
|
||||||
contentType string
|
contentType string
|
||||||
Draft bool
|
Draft bool
|
||||||
Aliases []string
|
Aliases []string
|
||||||
Tmpl *template.Template
|
Tmpl Template
|
||||||
Markup string
|
Markup string
|
||||||
PageMeta
|
PageMeta
|
||||||
File
|
File
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package hugolib
|
package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
|
@ -16,7 +16,6 @@ package hugolib
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
@ -37,7 +36,7 @@ type ShortcodeWithPage struct {
|
||||||
|
|
||||||
type Shortcodes map[string]ShortcodeFunc
|
type Shortcodes map[string]ShortcodeFunc
|
||||||
|
|
||||||
func ShortcodesHandle(stringToParse string, p *Page, t *template.Template) string {
|
func ShortcodesHandle(stringToParse string, p *Page, t Template) string {
|
||||||
posStart := strings.Index(stringToParse, "{{%")
|
posStart := strings.Index(stringToParse, "{{%")
|
||||||
if posStart > 0 {
|
if posStart > 0 {
|
||||||
posEnd := strings.Index(stringToParse[posStart:], "%}}") + posStart
|
posEnd := strings.Index(stringToParse[posStart:], "%}}") + posStart
|
||||||
|
@ -124,7 +123,7 @@ func SplitParams(in string) (name string, par2 string) {
|
||||||
return strings.TrimSpace(in[:i+1]), strings.TrimSpace(in[i+1:])
|
return strings.TrimSpace(in[:i+1]), strings.TrimSpace(in[i+1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func ShortcodeRender(name string, data *ShortcodeWithPage, t *template.Template) string {
|
func ShortcodeRender(name string, data *ShortcodeWithPage, t Template) string {
|
||||||
buffer := new(bytes.Buffer)
|
buffer := new(bytes.Buffer)
|
||||||
t.ExecuteTemplate(buffer, "shortcodes/"+name+".html", data)
|
t.ExecuteTemplate(buffer, "shortcodes/"+name+".html", data)
|
||||||
return buffer.String()
|
return buffer.String()
|
||||||
|
|
152
hugolib/site.go
152
hugolib/site.go
|
@ -16,12 +16,9 @@ package hugolib
|
||||||
import (
|
import (
|
||||||
"bitbucket.org/pkg/inflect"
|
"bitbucket.org/pkg/inflect"
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/hugo/target"
|
"github.com/spf13/hugo/target"
|
||||||
"github.com/spf13/nitro"
|
"github.com/spf13/nitro"
|
||||||
"html/template"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -33,7 +30,7 @@ var DefaultTimer = nitro.Initalize()
|
||||||
type Site struct {
|
type Site struct {
|
||||||
Config Config
|
Config Config
|
||||||
Pages Pages
|
Pages Pages
|
||||||
Tmpl *template.Template
|
Tmpl Template
|
||||||
Indexes IndexList
|
Indexes IndexList
|
||||||
Files []string
|
Files []string
|
||||||
Sections Index
|
Sections Index
|
||||||
|
@ -44,7 +41,7 @@ type Site struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SiteInfo struct {
|
type SiteInfo struct {
|
||||||
BaseUrl template.URL
|
BaseUrl URL
|
||||||
Indexes OrderedIndexList
|
Indexes OrderedIndexList
|
||||||
Recent *Pages
|
Recent *Pages
|
||||||
LastChange time.Time
|
LastChange time.Time
|
||||||
|
@ -70,8 +67,8 @@ func (s *Site) Build() (err error) {
|
||||||
if err = s.Render(); err != nil {
|
if err = s.Render(); err != nil {
|
||||||
fmt.Printf("Error rendering site: %s\n", err)
|
fmt.Printf("Error rendering site: %s\n", err)
|
||||||
fmt.Printf("Available templates:")
|
fmt.Printf("Available templates:")
|
||||||
for _, template := range s.Tmpl.Templates() {
|
for _, tpl := range s.Tmpl.Templates() {
|
||||||
fmt.Printf("\t%s\n", template.Name())
|
fmt.Printf("\t%s\n", tpl.Name())
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -84,6 +81,15 @@ func (s *Site) Analyze() {
|
||||||
s.checkDescriptions()
|
s.checkDescriptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Site) prepTemplates() {
|
||||||
|
s.Tmpl = NewTemplate()
|
||||||
|
s.Tmpl.LoadTemplates(s.absLayoutDir())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Site) addTemplate(name, data string) error {
|
||||||
|
return s.Tmpl.AddTemplate(name, data)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Site) Process() (err error) {
|
func (s *Site) Process() (err error) {
|
||||||
s.initialize()
|
s.initialize()
|
||||||
s.prepTemplates()
|
s.prepTemplates()
|
||||||
|
@ -136,65 +142,6 @@ func (s *Site) checkDescriptions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) prepTemplates() {
|
|
||||||
var templates = template.New("")
|
|
||||||
|
|
||||||
funcMap := template.FuncMap{
|
|
||||||
"urlize": Urlize,
|
|
||||||
"gt": Gt,
|
|
||||||
"isset": IsSet,
|
|
||||||
"echoParam": ReturnWhenSet,
|
|
||||||
}
|
|
||||||
|
|
||||||
templates.Funcs(funcMap)
|
|
||||||
|
|
||||||
s.Tmpl = templates
|
|
||||||
s.primeTemplates()
|
|
||||||
s.loadTemplates()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Site) loadTemplates() {
|
|
||||||
walker := func(path string, fi os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
|
||||||
PrintErr("Walker: ", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fi.IsDir() {
|
|
||||||
if ignoreDotFile(path) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
filetext, err := ioutil.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s.addTemplate(s.generateTemplateNameFrom(path), string(filetext))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
filepath.Walk(s.absLayoutDir(), walker)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Site) addTemplate(name, tmpl string) (err error) {
|
|
||||||
_, err = s.Tmpl.New(name).Parse(tmpl)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Site) generateTemplateNameFrom(path string) (name string) {
|
|
||||||
name = filepath.ToSlash(path[len(s.absLayoutDir())+1:])
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Site) primeTemplates() {
|
|
||||||
alias := "<!DOCTYPE html>\n <html>\n <head>\n <link rel=\"canonical\" href=\"{{ .Permalink }}\"/>\n <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n <meta http-equiv=\"refresh\" content=\"0;url={{ .Permalink }}\" />\n </head>\n </html>"
|
|
||||||
alias_xhtml := "<!DOCTYPE html>\n <html xmlns=\"http://www.w3.org/1999/xhtml\">\n <head>\n <link rel=\"canonical\" href=\"{{ .Permalink }}\"/>\n <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n <meta http-equiv=\"refresh\" content=\"0;url={{ .Permalink }}\" />\n </head>\n </html>"
|
|
||||||
|
|
||||||
s.addTemplate("alias", alias)
|
|
||||||
s.addTemplate("alias-xhtml", alias_xhtml)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Site) initialize() {
|
func (s *Site) initialize() {
|
||||||
s.checkDirectories()
|
s.checkDirectories()
|
||||||
|
|
||||||
|
@ -222,7 +169,7 @@ func (s *Site) initialize() {
|
||||||
|
|
||||||
filepath.Walk(s.absContentDir(), walker)
|
filepath.Walk(s.absContentDir(), walker)
|
||||||
s.Info = SiteInfo{
|
s.Info = SiteInfo{
|
||||||
BaseUrl: template.URL(s.Config.BaseUrl),
|
BaseUrl: URL(s.Config.BaseUrl),
|
||||||
Title: s.Config.Title,
|
Title: s.Config.Title,
|
||||||
Recent: &s.Pages,
|
Recent: &s.Pages,
|
||||||
Config: &s.Config,
|
Config: &s.Config,
|
||||||
|
@ -258,22 +205,22 @@ func (s *Site) checkDirectories() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) ProcessShortcodes() {
|
func (s *Site) ProcessShortcodes() {
|
||||||
for i, _ := range s.Pages {
|
for _, page := range s.Pages {
|
||||||
s.Pages[i].Content = HTML(ShortcodesHandle(string(s.Pages[i].Content), s.Pages[i], s.Tmpl))
|
page.Content = HTML(ShortcodesHandle(string(page.Content), page, s.Tmpl))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) AbsUrlify() {
|
func (s *Site) AbsUrlify() {
|
||||||
baseWithoutTrailingSlash := strings.TrimRight(s.Config.BaseUrl, "/")
|
baseWithoutTrailingSlash := strings.TrimRight(s.Config.BaseUrl, "/")
|
||||||
baseWithSlash := baseWithoutTrailingSlash + "/"
|
baseWithSlash := baseWithoutTrailingSlash + "/"
|
||||||
for i, _ := range s.Pages {
|
for _, page := range s.Pages {
|
||||||
content := string(s.Pages[i].Content)
|
content := string(page.Content)
|
||||||
content = strings.Replace(content, " src=\"/", " src=\""+baseWithSlash, -1)
|
content = strings.Replace(content, " src=\"/", " src=\""+baseWithSlash, -1)
|
||||||
content = strings.Replace(content, " src='/", " src='"+baseWithSlash, -1)
|
content = strings.Replace(content, " src='/", " src='"+baseWithSlash, -1)
|
||||||
content = strings.Replace(content, " href='/", " href='"+baseWithSlash, -1)
|
content = strings.Replace(content, " href='/", " href='"+baseWithSlash, -1)
|
||||||
content = strings.Replace(content, " href=\"/", " href=\""+baseWithSlash, -1)
|
content = strings.Replace(content, " href=\"/", " href=\""+baseWithSlash, -1)
|
||||||
content = strings.Replace(content, baseWithoutTrailingSlash+"//", baseWithSlash, -1)
|
content = strings.Replace(content, baseWithoutTrailingSlash+"//", baseWithSlash, -1)
|
||||||
s.Pages[i].Content = HTML(content)
|
page.Content = HTML(content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,13 +241,13 @@ func (s *Site) CreatePages() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) setupPrevNext() {
|
func (s *Site) setupPrevNext() {
|
||||||
for i, _ := range s.Pages {
|
for i, page := range s.Pages {
|
||||||
if i < len(s.Pages)-1 {
|
if i < len(s.Pages)-1 {
|
||||||
s.Pages[i].Next = s.Pages[i+1]
|
page.Next = s.Pages[i+1]
|
||||||
}
|
}
|
||||||
|
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
s.Pages[i].Prev = s.Pages[i-1]
|
page.Prev = s.Pages[i-1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,7 +257,7 @@ func (s *Site) setUrlPath(p *Page) error {
|
||||||
x := strings.Split(y, string(os.PathSeparator))
|
x := strings.Split(y, string(os.PathSeparator))
|
||||||
|
|
||||||
if len(x) <= 1 {
|
if len(x) <= 1 {
|
||||||
return errors.New("Zero length page name")
|
return fmt.Errorf("Zero length page name")
|
||||||
}
|
}
|
||||||
|
|
||||||
p.Section = strings.Trim(x[1], "/\\")
|
p.Section = strings.Trim(x[1], "/\\")
|
||||||
|
@ -361,14 +308,14 @@ func (s *Site) BuildSiteMeta() (err error) {
|
||||||
|
|
||||||
for _, plural := range s.Config.Indexes {
|
for _, plural := range s.Config.Indexes {
|
||||||
s.Indexes[plural] = make(Index)
|
s.Indexes[plural] = make(Index)
|
||||||
for i, p := range s.Pages {
|
for _, p := range s.Pages {
|
||||||
vals := p.GetParam(plural)
|
vals := p.GetParam(plural)
|
||||||
|
|
||||||
if vals != nil {
|
if vals != nil {
|
||||||
v, ok := vals.([]string)
|
v, ok := vals.([]string)
|
||||||
if ok {
|
if ok {
|
||||||
for _, idx := range v {
|
for _, idx := range v {
|
||||||
s.Indexes[plural].Add(idx, s.Pages[i])
|
s.Indexes[plural].Add(idx, p)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PrintErr("Invalid " + plural + " in " + p.File.FileName)
|
PrintErr("Invalid " + plural + " in " + p.File.FileName)
|
||||||
|
@ -380,8 +327,8 @@ func (s *Site) BuildSiteMeta() (err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, p := range s.Pages {
|
for _, p := range s.Pages {
|
||||||
s.Sections.Add(p.Section, s.Pages[i])
|
s.Sections.Add(p.Section, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, _ := range s.Sections {
|
for k, _ := range s.Sections {
|
||||||
|
@ -424,13 +371,13 @@ func inStringArray(arr []string, el string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) RenderAliases() error {
|
func (s *Site) RenderAliases() error {
|
||||||
for i, p := range s.Pages {
|
for _, p := range s.Pages {
|
||||||
for _, a := range p.Aliases {
|
for _, a := range p.Aliases {
|
||||||
t := "alias"
|
t := "alias"
|
||||||
if strings.HasSuffix(a, ".xhtml") {
|
if strings.HasSuffix(a, ".xhtml") {
|
||||||
t = "alias-xhtml"
|
t = "alias-xhtml"
|
||||||
}
|
}
|
||||||
content, err := s.RenderThing(s.Pages[i], t)
|
content, err := s.RenderThing(p, t)
|
||||||
if strings.HasSuffix(a, "/") {
|
if strings.HasSuffix(a, "/") {
|
||||||
a = a + "index.html"
|
a = a + "index.html"
|
||||||
}
|
}
|
||||||
|
@ -447,12 +394,12 @@ func (s *Site) RenderAliases() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) RenderPages() error {
|
func (s *Site) RenderPages() error {
|
||||||
for i, _ := range s.Pages {
|
for _, p := range s.Pages {
|
||||||
content, err := s.RenderThingOrDefault(s.Pages[i], s.Pages[i].Layout(), "_default/single.html")
|
content, err := s.RenderThingOrDefault(p, p.Layout(), "_default/single.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.Pages[i].RenderedContent = content
|
p.RenderedContent = content
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -480,8 +427,8 @@ func (s *Site) RenderIndexes() error {
|
||||||
} else {
|
} else {
|
||||||
n.Url = url + "/index.html"
|
n.Url = url + "/index.html"
|
||||||
}
|
}
|
||||||
n.Permalink = HTML(MakePermalink(string(n.Site.BaseUrl), string(plink)))
|
n.Permalink = permalink(s, plink)
|
||||||
n.RSSlink = HTML(MakePermalink(string(n.Site.BaseUrl), string(url+".xml")))
|
n.RSSlink = permalink(s, url+".xml")
|
||||||
n.Date = o[0].Date
|
n.Date = o[0].Date
|
||||||
n.Data[singular] = o
|
n.Data[singular] = o
|
||||||
n.Data["Pages"] = o
|
n.Data["Pages"] = o
|
||||||
|
@ -511,7 +458,7 @@ func (s *Site) RenderIndexes() error {
|
||||||
} else {
|
} else {
|
||||||
n.Url = Urlize(plural + "/" + k + "/" + "index.xml")
|
n.Url = Urlize(plural + "/" + k + "/" + "index.xml")
|
||||||
}
|
}
|
||||||
n.Permalink = HTML(string(n.Site.BaseUrl) + n.Url)
|
n.Permalink = permalink(s, n.Url)
|
||||||
s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
|
s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
|
||||||
err = s.WritePublic(base+".xml", y.Bytes())
|
err = s.WritePublic(base+".xml", y.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -531,7 +478,7 @@ func (s *Site) RenderIndexesIndexes() (err error) {
|
||||||
n.Title = strings.Title(plural)
|
n.Title = strings.Title(plural)
|
||||||
url := Urlize(plural)
|
url := Urlize(plural)
|
||||||
n.Url = url + "/index.html"
|
n.Url = url + "/index.html"
|
||||||
n.Permalink = HTML(MakePermalink(string(n.Site.BaseUrl), string(n.Url)))
|
n.Permalink = permalink(s, n.Url)
|
||||||
n.Data["Singular"] = singular
|
n.Data["Singular"] = singular
|
||||||
n.Data["Plural"] = plural
|
n.Data["Plural"] = plural
|
||||||
n.Data["Index"] = s.Indexes[plural]
|
n.Data["Index"] = s.Indexes[plural]
|
||||||
|
@ -556,8 +503,8 @@ func (s *Site) RenderLists() error {
|
||||||
n := s.NewNode()
|
n := s.NewNode()
|
||||||
n.Title = strings.Title(inflect.Pluralize(section))
|
n.Title = strings.Title(inflect.Pluralize(section))
|
||||||
n.Url = Urlize(section + "/" + "index.html")
|
n.Url = Urlize(section + "/" + "index.html")
|
||||||
n.Permalink = HTML(MakePermalink(string(n.Site.BaseUrl), string(n.Url)))
|
n.Permalink = permalink(s, n.Url)
|
||||||
n.RSSlink = HTML(MakePermalink(string(n.Site.BaseUrl), string(section+".xml")))
|
n.RSSlink = permalink(s, section+".xml")
|
||||||
n.Date = data[0].Date
|
n.Date = data[0].Date
|
||||||
n.Data["Pages"] = data
|
n.Data["Pages"] = data
|
||||||
layout := "indexes/" + section + ".html"
|
layout := "indexes/" + section + ".html"
|
||||||
|
@ -592,8 +539,8 @@ func (s *Site) RenderHomePage() error {
|
||||||
n := s.NewNode()
|
n := s.NewNode()
|
||||||
n.Title = n.Site.Title
|
n.Title = n.Site.Title
|
||||||
n.Url = Urlize(string(n.Site.BaseUrl))
|
n.Url = Urlize(string(n.Site.BaseUrl))
|
||||||
n.RSSlink = HTML(MakePermalink(string(n.Site.BaseUrl), string("index.xml")))
|
n.RSSlink = permalink(s, "index.xml")
|
||||||
n.Permalink = HTML(string(n.Site.BaseUrl))
|
n.Permalink = permalink(s, "")
|
||||||
if len(s.Pages) > 0 {
|
if len(s.Pages) > 0 {
|
||||||
n.Date = s.Pages[0].Date
|
n.Date = s.Pages[0].Date
|
||||||
if len(s.Pages) < 9 {
|
if len(s.Pages) < 9 {
|
||||||
|
@ -615,7 +562,7 @@ func (s *Site) RenderHomePage() error {
|
||||||
// XML Feed
|
// XML Feed
|
||||||
n.Url = Urlize("index.xml")
|
n.Url = Urlize("index.xml")
|
||||||
n.Title = "Recent Content"
|
n.Title = "Recent Content"
|
||||||
n.Permalink = HTML(string(n.Site.BaseUrl) + "index.xml")
|
n.Permalink = permalink(s, "index.xml")
|
||||||
y := s.NewXMLBuffer()
|
y := s.NewXMLBuffer()
|
||||||
s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
|
s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
|
||||||
err = s.WritePublic("index.xml", y.Bytes())
|
err = s.WritePublic("index.xml", y.Bytes())
|
||||||
|
@ -625,7 +572,7 @@ func (s *Site) RenderHomePage() error {
|
||||||
if a := s.Tmpl.Lookup("404.html"); a != nil {
|
if a := s.Tmpl.Lookup("404.html"); a != nil {
|
||||||
n.Url = Urlize("404.html")
|
n.Url = Urlize("404.html")
|
||||||
n.Title = "404 Page not found"
|
n.Title = "404 Page not found"
|
||||||
n.Permalink = HTML(string(n.Site.BaseUrl) + "404.html")
|
n.Permalink = permalink(s, "404.html")
|
||||||
x, err := s.RenderThing(n, "404.html")
|
x, err := s.RenderThing(n, "404.html")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -644,15 +591,20 @@ func (s *Site) Stats() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) NewNode() (y Node) {
|
func permalink(s *Site, plink string) HTML {
|
||||||
y.Data = make(map[string]interface{})
|
return HTML(MakePermalink(string(s.Info.BaseUrl), plink))
|
||||||
y.Site = s.Info
|
}
|
||||||
return y
|
|
||||||
|
func (s *Site) NewNode() *Node {
|
||||||
|
return &Node{
|
||||||
|
Data: make(map[string]interface{}),
|
||||||
|
Site: s.Info,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Site) RenderThing(d interface{}, layout string) (*bytes.Buffer, error) {
|
func (s *Site) RenderThing(d interface{}, layout string) (*bytes.Buffer, error) {
|
||||||
if s.Tmpl.Lookup(layout) == nil {
|
if s.Tmpl.Lookup(layout) == nil {
|
||||||
return nil, errors.New(fmt.Sprintf("Layout not found: %s", layout))
|
return nil, fmt.Errorf("Layout not found: %s", layout)
|
||||||
}
|
}
|
||||||
buffer := new(bytes.Buffer)
|
buffer := new(bytes.Buffer)
|
||||||
err := s.Tmpl.ExecuteTemplate(buffer, layout, d)
|
err := s.Tmpl.ExecuteTemplate(buffer, layout, d)
|
||||||
|
|
|
@ -39,10 +39,9 @@ func TestDegenerateRenderThingMissingTemplate(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrimeTempaltes(t *testing.T) {
|
func TestPrimeTemplates(t *testing.T) {
|
||||||
s := new(Site)
|
s := new(Site)
|
||||||
s.prepTemplates()
|
s.prepTemplates()
|
||||||
s.primeTemplates()
|
|
||||||
if s.Tmpl.Lookup("alias") == nil {
|
if s.Tmpl.Lookup("alias") == nil {
|
||||||
t.Fatalf("alias template not created.")
|
t.Fatalf("alias template not created.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
package hugolib
|
package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"github.com/eknkc/amber"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HTML encapsulates a known safe HTML document fragment.
|
// HTML encapsulates a known safe HTML document fragment.
|
||||||
|
@ -9,3 +15,112 @@ import (
|
||||||
// unclosed tags or comments. The outputs of a sound HTML sanitizer
|
// unclosed tags or comments. The outputs of a sound HTML sanitizer
|
||||||
// and a template escaped by this package are fine for use with HTML.
|
// and a template escaped by this package are fine for use with HTML.
|
||||||
type HTML template.HTML
|
type HTML template.HTML
|
||||||
|
|
||||||
|
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)
|
||||||
|
AddTemplate(name, tpl string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type URL template.URL
|
||||||
|
|
||||||
|
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),
|
||||||
|
}
|
||||||
|
|
||||||
|
funcMap := template.FuncMap{
|
||||||
|
"urlize": Urlize,
|
||||||
|
"gt": Gt,
|
||||||
|
"isset": IsSet,
|
||||||
|
"echoParam": ReturnWhenSet,
|
||||||
|
}
|
||||||
|
|
||||||
|
templates.Funcs(funcMap)
|
||||||
|
templates.primeTemplates()
|
||||||
|
return templates
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *GoHtmlTemplate) AddTemplate(name, tpl string) error {
|
||||||
|
_, err := t.New(name).Parse(tpl)
|
||||||
|
if err != nil {
|
||||||
|
t.errors = append(t.errors, &templateErr{name: name, err: err})
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *GoHtmlTemplate) AddTemplateFile(name, path string) error {
|
||||||
|
b, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
s := string(b)
|
||||||
|
_, err = t.New(name).Parse(s)
|
||||||
|
if err != nil {
|
||||||
|
t.errors = append(t.errors, &templateErr{name: name, err: err})
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *GoHtmlTemplate) generateTemplateNameFrom(base, path string) string {
|
||||||
|
return filepath.ToSlash(path[len(base)+1:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *GoHtmlTemplate) primeTemplates() {
|
||||||
|
alias := "<!DOCTYPE html>\n <html>\n <head>\n <link rel=\"canonical\" href=\"{{ .Permalink }}\"/>\n <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n <meta http-equiv=\"refresh\" content=\"0;url={{ .Permalink }}\" />\n </head>\n </html>"
|
||||||
|
alias_xhtml := "<!DOCTYPE html>\n <html xmlns=\"http://www.w3.org/1999/xhtml\">\n <head>\n <link rel=\"canonical\" href=\"{{ .Permalink }}\"/>\n <meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n <meta http-equiv=\"refresh\" content=\"0;url={{ .Permalink }}\" />\n </head>\n </html>"
|
||||||
|
|
||||||
|
t.AddTemplate("alias", alias)
|
||||||
|
t.AddTemplate("alias-xhtml", alias_xhtml)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *GoHtmlTemplate) LoadTemplates(absPath string) {
|
||||||
|
walker := func(path string, fi os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
PrintErr("Walker: ", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !fi.IsDir() {
|
||||||
|
if ignoreDotFile(path) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
tplName := t.generateTemplateNameFrom(absPath, path)
|
||||||
|
|
||||||
|
if strings.HasSuffix(path, ".amber") {
|
||||||
|
compiler := amber.New()
|
||||||
|
// Parse the input file
|
||||||
|
if err := compiler.ParseFile(path); err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// note t.New(tplName)
|
||||||
|
if _, err := compiler.CompileWithTemplate(t.New(tplName)); err != nil {
|
||||||
|
PrintErr("Could not compile amber file: "+path, err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
t.AddTemplateFile(tplName, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
filepath.Walk(absPath, walker)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue