shithub: hugo

Download patch

ref: 4a8de8ea46f45776518c7086222be0c94c893764
parent: 41adafbc3e8c53475ba9a8bc8031dd4e0bf59664
author: spf13 <[email protected]>
date: Tue Apr 22 22:52:01 EDT 2014

Add Disqus support out of the box. Move template/bundle into hugolib.

--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -28,7 +28,6 @@
 	"github.com/spf13/cast"
 	"github.com/spf13/hugo/helpers"
 	"github.com/spf13/hugo/parser"
-	"github.com/spf13/hugo/template/bundle"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/viper"
 	"github.com/theplant/blackfriday"
@@ -49,7 +48,7 @@
 	contentType     string
 	Draft           bool
 	Aliases         []string
-	Tmpl            bundle.Template
+	Tmpl            Template
 	Markup          string
 	renderable      bool
 	layout          string
@@ -519,7 +518,7 @@
 	return nil
 }
 
-func (p *Page) ProcessShortcodes(t bundle.Template) {
+func (p *Page) ProcessShortcodes(t Template) {
 	p.rawContent = []byte(ShortcodesHandle(string(p.rawContent), p, t))
 	p.Summary = template.HTML(ShortcodesHandle(string(p.Summary), p, t))
 }
--- /dev/null
+++ b/hugolib/path_seperators_windows_test.go
@@ -1,0 +1,17 @@
+package hugolib
+
+import (
+	"testing"
+)
+
+const (
+	win_base = "c:\\a\\windows\\path\\layout"
+	win_path = "c:\\a\\windows\\path\\layout\\sub1\\index.html"
+)
+
+func TestTemplatePathSeperator(t *testing.T) {
+	tmpl := new(GoHtmlTemplate)
+	if name := tmpl.generateTemplateNameFrom(win_base, win_path); name != "sub1/index.html" {
+		t.Fatalf("Template name incorrect.  Expected: %s, Got: %s", "sub1/index.html", name)
+	}
+}
--- a/hugolib/shortcode.go
+++ b/hugolib/shortcode.go
@@ -20,7 +20,6 @@
 	"strings"
 	"unicode"
 
-	"github.com/spf13/hugo/template/bundle"
 	jww "github.com/spf13/jwalterweatherman"
 )
 
@@ -78,7 +77,7 @@
 
 type Shortcodes map[string]ShortcodeFunc
 
-func ShortcodesHandle(stringToParse string, p *Page, t bundle.Template) string {
+func ShortcodesHandle(stringToParse string, p *Page, t Template) string {
 	leadStart := strings.Index(stringToParse, `{{%`)
 	if leadStart >= 0 {
 		leadEnd := strings.Index(stringToParse[leadStart:], `%}}`) + leadStart
@@ -147,7 +146,7 @@
 	return startPos, endPos
 }
 
-func GetTemplate(name string, t bundle.Template) *template.Template {
+func GetTemplate(name string, t Template) *template.Template {
 	if x := t.Lookup("shortcodes/" + name + ".html"); x != nil {
 		return x
 	}
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -27,7 +27,6 @@
 	"github.com/spf13/hugo/helpers"
 	"github.com/spf13/hugo/source"
 	"github.com/spf13/hugo/target"
-	"github.com/spf13/hugo/template/bundle"
 	"github.com/spf13/hugo/transform"
 	jww "github.com/spf13/jwalterweatherman"
 	"github.com/spf13/nitro"
@@ -57,7 +56,7 @@
 // 5. The entire collection of files is written to disk.
 type Site struct {
 	Pages      Pages
-	Tmpl       bundle.Template
+	Tmpl       Template
 	Taxonomies TaxonomyList
 	Source     source.Input
 	Sections   Taxonomy
@@ -72,20 +71,21 @@
 }
 
 type SiteInfo struct {
-	BaseUrl      template.URL
-	Taxonomies   TaxonomyList
-	Indexes      *TaxonomyList // legacy, should be identical to Taxonomies
-	Recent       *Pages
-	Title        string
-	Author       string
-	AuthorEmail  string
-	LanguageCode string
-	Copyright    string
-	LastChange   time.Time
-	ConfigGet    func(key string) interface{}
-	Permalinks   PermalinkOverrides
-	Params       map[string]interface{}
+	BaseUrl         template.URL
+	Taxonomies      TaxonomyList
+	Indexes         *TaxonomyList // legacy, should be identical to Taxonomies
+	Recent          *Pages
+	Title           string
+	Author          map[string]string
+	LanguageCode    string
+	DisqusShortname string
+	Copyright       string
+	LastChange      time.Time
+	ConfigGet       func(key string) interface{}
+	Permalinks      PermalinkOverrides
+	Params          map[string]interface{}
 }
+}
 
 type runmode struct {
 	Watching bool
@@ -130,7 +130,7 @@
 }
 
 func (s *Site) prepTemplates() {
-	s.Tmpl = bundle.NewTemplate()
+	s.Tmpl = NewTemplate()
 	s.Tmpl.LoadTemplates(s.absLayoutDir())
 	if s.hasTheme() {
 		s.Tmpl.LoadTemplatesWithPrefix(s.absThemeDir()+"/layouts", "theme")
@@ -234,16 +234,16 @@
 		permalinks = make(PermalinkOverrides)
 	}
 
-	s.Info = SiteInfo{
-		BaseUrl:      template.URL(helpers.SanitizeUrl(viper.GetString("BaseUrl"))),
-		Title:        viper.GetString("Title"),
-		Author:       viper.GetString("author"),
-		AuthorEmail:  viper.GetString("authoremail"),
-		LanguageCode: viper.GetString("languagecode"),
-		Copyright:    viper.GetString("copyright"),
-		Recent:       &s.Pages,
-		Params:       params,
-		Permalinks:   permalinks,
+	s.Info = &SiteInfo{
+		BaseUrl:         template.URL(helpers.SanitizeUrl(viper.GetString("BaseUrl"))),
+		Title:           viper.GetString("Title"),
+		Author:          viper.GetStringMapString("author"),
+		LanguageCode:    viper.GetString("languagecode"),
+		Copyright:       viper.GetString("copyright"),
+		DisqusShortname: viper.GetString("DisqusShortname"),
+		Recent:          &s.Pages,
+		Params:          params,
+		Permalinks:      permalinks,
 	}
 }
 
--- /dev/null
+++ b/hugolib/template.go
@@ -1,0 +1,275 @@
+package hugolib
+
+import (
+	"errors"
+	"html"
+	"html/template"
+	"io"
+	"io/ioutil"
+	"os"
+	"path/filepath"
+	"reflect"
+	"strconv"
+	"strings"
+
+	"github.com/eknkc/amber"
+	"github.com/spf13/hugo/helpers"
+)
+
+func Gt(a interface{}, b interface{}) bool {
+	var left, right int64
+	av := reflect.ValueOf(a)
+
+	switch av.Kind() {
+	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
+		left = int64(av.Len())
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		left = av.Int()
+	case reflect.String:
+		left, _ = strconv.ParseInt(av.String(), 10, 64)
+	}
+
+	bv := reflect.ValueOf(b)
+
+	switch bv.Kind() {
+	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
+		right = int64(bv.Len())
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		right = bv.Int()
+	case reflect.String:
+		right, _ = strconv.ParseInt(bv.String(), 10, 64)
+	}
+
+	return left > right
+}
+
+// First is exposed to templates, to iterate over the first N items in a
+// rangeable list.
+func First(limit int, seq interface{}) (interface{}, error) {
+	if limit < 1 {
+		return nil, errors.New("can't return negative/empty count of items from sequence")
+	}
+
+	seqv := reflect.ValueOf(seq)
+	// this is better than my first pass; ripped from text/template/exec.go indirect():
+	for ; seqv.Kind() == reflect.Ptr || seqv.Kind() == reflect.Interface; seqv = seqv.Elem() {
+		if seqv.IsNil() {
+			return nil, errors.New("can't iterate over a nil value")
+		}
+		if seqv.Kind() == reflect.Interface && seqv.NumMethod() > 0 {
+			break
+		}
+	}
+
+	switch seqv.Kind() {
+	case reflect.Array, reflect.Slice, reflect.String:
+		// okay
+	default:
+		return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
+	}
+	if limit > seqv.Len() {
+		limit = seqv.Len()
+	}
+	return seqv.Slice(0, limit).Interface(), nil
+}
+
+func IsSet(a interface{}, key interface{}) bool {
+	av := reflect.ValueOf(a)
+	kv := reflect.ValueOf(key)
+
+	switch av.Kind() {
+	case reflect.Array, reflect.Chan, reflect.Slice:
+		if int64(av.Len()) > kv.Int() {
+			return true
+		}
+	case reflect.Map:
+		if kv.Type() == av.Type().Key() {
+			return av.MapIndex(kv).IsValid()
+		}
+	}
+
+	return false
+}
+
+func ReturnWhenSet(a interface{}, index int) interface{} {
+	av := reflect.ValueOf(a)
+
+	switch av.Kind() {
+	case reflect.Array, reflect.Slice:
+		if av.Len() > index {
+
+			avv := av.Index(index)
+			switch avv.Kind() {
+			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+				return avv.Int()
+			case reflect.String:
+				return avv.String()
+			}
+		}
+	}
+
+	return ""
+}
+
+func Highlight(in interface{}, lang string) template.HTML {
+	var str string
+	av := reflect.ValueOf(in)
+	switch av.Kind() {
+	case reflect.String:
+		str = av.String()
+	}
+
+	if strings.HasPrefix(strings.TrimSpace(str), "<pre><code>") {
+		str = str[strings.Index(str, "<pre><code>")+11:]
+	}
+	if strings.HasSuffix(strings.TrimSpace(str), "</code></pre>") {
+		str = str[:strings.LastIndex(str, "</code></pre>")]
+	}
+	return template.HTML(helpers.Highlight(html.UnescapeString(str), lang))
+}
+
+func SafeHtml(text string) template.HTML {
+	return template.HTML(text)
+}
+
+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),
+	}
+
+	funcMap := template.FuncMap{
+		"urlize":      helpers.Urlize,
+		"sanitizeurl": helpers.SanitizeUrl,
+		"gt":          Gt,
+		"isset":       IsSet,
+		"echoParam":   ReturnWhenSet,
+		"safeHtml":    SafeHtml,
+		"first":       First,
+		"highlight":   Highlight,
+		"add":         func(a, b int) int { return a + b },
+		"sub":         func(a, b int) int { return a - b },
+		"div":         func(a, b int) int { return a / b },
+		"mod":         func(a, b int) int { return a % b },
+		"mul":         func(a, b int) int { return a * b },
+		"modBool":     func(a, b int) bool { return a%b == 0 },
+		"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) },
+	}
+
+	templates.Funcs(funcMap)
+
+	templates.LoadEmbedded()
+	return templates
+}
+
+func (t *GoHtmlTemplate) LoadEmbedded() {
+	t.EmbedShortcodes()
+	t.EmbedTemplates()
+}
+
+func (t *GoHtmlTemplate) AddInternalTemplate(prefix, name, tpl string) error {
+	if prefix != "" {
+		return t.AddTemplate("_internal/"+prefix+"/"+name, tpl)
+	} else {
+		return t.AddTemplate("_internal/"+name, tpl)
+	}
+}
+
+func (t *GoHtmlTemplate) AddInternalShortcode(name, content string) error {
+	return t.AddInternalTemplate("shortcodes", name, content)
+}
+
+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
+	}
+	return t.AddTemplate(name, string(b))
+}
+
+func (t *GoHtmlTemplate) generateTemplateNameFrom(base, path string) string {
+	return filepath.ToSlash(path[len(base)+1:])
+}
+
+func ignoreDotFile(path string) bool {
+	return filepath.Base(path)[0] == '.'
+}
+
+func (t *GoHtmlTemplate) loadTemplates(absPath string, prefix string) {
+	walker := func(path string, fi os.FileInfo, err error) error {
+		if err != nil {
+			return nil
+		}
+
+		if !fi.IsDir() {
+			if ignoreDotFile(path) {
+				return nil
+			}
+
+			tplName := t.generateTemplateNameFrom(absPath, path)
+
+			if prefix != "" {
+				tplName = strings.Trim(prefix, "/") + "/" + tplName
+			}
+
+			// TODO move this into the AddTemplateFile function
+			if strings.HasSuffix(path, ".amber") {
+				compiler := amber.New()
+				// Parse the input file
+				if err := compiler.ParseFile(path); err != nil {
+					return nil
+				}
+
+				if _, err := compiler.CompileWithTemplate(t.New(tplName)); err != nil {
+					return err
+				}
+
+			} else {
+				t.AddTemplateFile(tplName, path)
+			}
+		}
+		return nil
+	}
+
+	filepath.Walk(absPath, walker)
+}
+
+func (t *GoHtmlTemplate) LoadTemplatesWithPrefix(absPath string, prefix string) {
+	t.loadTemplates(absPath, prefix)
+}
+
+func (t *GoHtmlTemplate) LoadTemplates(absPath string) {
+	t.loadTemplates(absPath, "")
+}
--- /dev/null
+++ b/hugolib/template_embedded.go
@@ -1,0 +1,84 @@
+// Copyright © 2013 Steve Francia <[email protected]>.
+//
+// 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 hugolib
+
+type Tmpl struct {
+	Name string
+	Data string
+}
+
+func (t *GoHtmlTemplate) EmbedShortcodes() {
+	t.AddInternalShortcode("highlight.html", `{{ .Get 0 | highlight .Inner  }}`)
+	t.AddInternalShortcode("test.html", `This is a simple Test`)
+	t.AddInternalShortcode("figure.html", `<!-- image -->
+<figure {{ with .Get "class" }}class="{{.}}"{{ end }}>
+    {{ with .Get "link"}}<a href="{{.}}">{{ end }}
+        <img src="{{ .Get "src" }}" {{ if or (.Get "alt") (.Get "caption") }}alt="{{ with .Get "alt"}}{{.}}{{else}}{{ .Get "caption" }}{{ end }}"{{ end }} />
+    {{ if .Get "link"}}</a>{{ end }}
+    {{ if or (or (.Get "title") (.Get "caption")) (.Get "attr")}}
+    <figcaption>{{ if isset .Params "title" }}
+        <h4>{{ .Get "title" }}</h4>{{ end }}
+        {{ if or (.Get "caption") (.Get "attr")}}<p>
+        {{ .Get "caption" }}
+        {{ with .Get "attrlink"}}<a href="{{.}}"> {{ end }}
+            {{ .Get "attr" }}
+        {{ if .Get "attrlink"}}</a> {{ end }}
+        </p> {{ end }}
+    </figcaption>
+    {{ end }}
+</figure>
+<!-- image -->`)
+}
+
+func (t *GoHtmlTemplate) EmbedTemplates() {
+
+	t.AddInternalTemplate("_default", "rss.xml", `<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
+  <channel>
+      <title>{{ .Title }} on {{ .Site.Title }} </title>
+      <generator uri="https://hugo.spf13.com">Hugo</generator>
+    <link>{{ .Permalink }}</link>
+    {{ with .Site.LanguageCode }}<language>{{.}}</language>{{end}}
+    {{ with .Site.Author.name }}<author>{{.}}</author>{{end}}
+    {{ with .Site.Copyright }}<copyright>{{.}}</copyright>{{end}}
+    <updated>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 MST" }}</updated>
+    {{ range first 15 .Data.Pages }}
+    <item>
+      <title>{{ .Title }}</title>
+      <link>{{ .Permalink }}</link>
+      <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 MST" }}</pubDate>
+      {{with .Site.Author.name}}<author>{{.}}</author>{{end}}
+      <guid>{{ .Permalink }}</guid>
+      <description>{{ .Content | html }}</description>
+    </item>
+    {{ end }}
+  </channel>
+</rss>`)
+
+	t.AddInternalTemplate("", "disqus.html", `{{ if .Site.DisqusShortname }}<div id="disqus_thread"></div>
+<script type="text/javascript">
+    var disqus_shortname = '{{ .Site.DisqusShortname }}';
+    var disqus_identifier = '{{with .GetParam "disqus_identifier" }}{{ . }}{{ else }}{{ .Permalink }}{{end}}';
+    var disqus_title = '{{with .GetParam "disqus_title" }}{{ . }}{{ else }}{{ .Title }}{{end}}';
+    var disqus_url = '{{with .GetParam "disqus_url" }}{{ . | html  }}{{ else }}{{ .Permalink }}{{end}}';
+
+    (function() {
+        var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
+        dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
+        (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
+    })();
+</script>
+<noscript>Please enable JavaScript to view the <a href="http://disqus.com/?ref_noscript">comments powered by Disqus.</a></noscript>
+<a href="http://disqus.com" class="dsq-brlink">comments powered by <span class="logo-disqus">Disqus</span></a>{{end}}`)
+
+}
--- /dev/null
+++ b/hugolib/template_test.go
@@ -1,0 +1,55 @@
+package hugolib
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestGt(t *testing.T) {
+	for i, this := range []struct {
+		left          interface{}
+		right         interface{}
+		leftShouldWin bool
+	}{
+		{5, 8, false},
+		{8, 5, true},
+		{5, 5, false},
+		{-2, 1, false},
+		{2, -5, true},
+		{"8", "5", true},
+		{"5", "0001", true},
+		{[]int{100, 99}, []int{1, 2, 3, 4}, false},
+	} {
+		leftIsBigger := Gt(this.left, this.right)
+		if leftIsBigger != this.leftShouldWin {
+			var which string
+			if leftIsBigger {
+				which = "expected right to be bigger, but left was"
+			} else {
+				which = "expected left to be bigger, but right was"
+			}
+			t.Errorf("[%d] %v compared to %v: %s", i, this.left, this.right, which)
+		}
+	}
+}
+
+func TestFirst(t *testing.T) {
+	for i, this := range []struct {
+		count    int
+		sequence interface{}
+		expect   interface{}
+	}{
+		{2, []string{"a", "b", "c"}, []string{"a", "b"}},
+		{3, []string{"a", "b"}, []string{"a", "b"}},
+		{2, []int{100, 200, 300}, []int{100, 200}},
+	} {
+		results, err := First(this.count, this.sequence)
+		if err != nil {
+			t.Errorf("[%d] failed: %s", i, err)
+			continue
+		}
+		if !reflect.DeepEqual(results, this.expect) {
+			t.Errorf("[%d] First %d items, got %v but expected %v", i, this.count, results, this.expect)
+		}
+	}
+}
--- a/template/bundle/embedded.go
+++ /dev/null
@@ -1,68 +1,0 @@
-// Copyright © 2013 Steve Francia <[email protected]>.
-//
-// 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 bundle
-
-type Tmpl struct {
-	Name string
-	Data string
-}
-
-func (t *GoHtmlTemplate) EmbedShortcodes() {
-	t.AddInternalShortcode("highlight.html", `{{ .Get 0 | highlight .Inner  }}`)
-	t.AddInternalShortcode("test.html", `This is a simple Test`)
-	t.AddInternalShortcode("figure.html", `<!-- image -->
-<figure {{ with .Get "class" }}class="{{.}}"{{ end }}>
-    {{ with .Get "link"}}<a href="{{.}}">{{ end }}
-        <img src="{{ .Get "src" }}" {{ if or (.Get "alt") (.Get "caption") }}alt="{{ with .Get "alt"}}{{.}}{{else}}{{ .Get "caption" }}{{ end }}"{{ end }} />
-    {{ if .Get "link"}}</a>{{ end }}
-    {{ if or (or (.Get "title") (.Get "caption")) (.Get "attr")}}
-    <figcaption>{{ if isset .Params "title" }}
-        <h4>{{ .Get "title" }}</h4>{{ end }}
-        {{ if or (.Get "caption") (.Get "attr")}}<p>
-        {{ .Get "caption" }}
-        {{ with .Get "attrlink"}}<a href="{{.}}"> {{ end }}
-            {{ .Get "attr" }}
-        {{ if .Get "attrlink"}}</a> {{ end }}
-        </p> {{ end }}
-    </figcaption>
-    {{ end }}
-</figure>
-<!-- image -->`)
-}
-
-func (t *GoHtmlTemplate) EmbedTemplates() {
-
-	t.AddInternalTemplate("_default", "rss.xml", `<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
-  <channel>
-      <title>{{ .Title }} on {{ .Site.Title }} </title>
-      <generator uri="https://hugo.spf13.com">Hugo</generator>
-    <link>{{ .Permalink }}</link>
-    {{ with .Site.LanguageCode }}<language>{{.}}</language>{{end}}
-    {{ with .Site.Author }}<author>{{.}}</author>{{end}}
-    {{ with .Site.Copyright }}<copyright>{{.}}</copyright>{{end}}
-    <updated>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 MST" }}</updated>
-    {{ range first 15 .Data.Pages }}
-    <item>
-      <title>{{ .Title }}</title>
-      <link>{{ .Permalink }}</link>
-      <pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 MST" }}</pubDate>
-      {{with .Site.Author}}<author>{{.}}</author>{{end}}
-      <guid>{{ .Permalink }}</guid>
-      <description>{{ .Content | html }}</description>
-    </item>
-    {{ end }}
-  </channel>
-</rss>`)
-
-}
--- a/template/bundle/path_seperators_windows_test.go
+++ /dev/null
@@ -1,17 +1,0 @@
-package bundle
-
-import (
-	"testing"
-)
-
-const (
-	win_base = "c:\\a\\windows\\path\\layout"
-	win_path = "c:\\a\\windows\\path\\layout\\sub1\\index.html"
-)
-
-func TestTemplatePathSeperator(t *testing.T) {
-	tmpl := new(GoHtmlTemplate)
-	if name := tmpl.generateTemplateNameFrom(win_base, win_path); name != "sub1/index.html" {
-		t.Fatalf("Template name incorrect.  Expected: %s, Got: %s", "sub1/index.html", name)
-	}
-}
--- a/template/bundle/template.go
+++ /dev/null
@@ -1,271 +1,0 @@
-package bundle
-
-import (
-	"errors"
-	"html"
-	"html/template"
-	"io"
-	"io/ioutil"
-	"os"
-	"path/filepath"
-	"reflect"
-	"strconv"
-	"strings"
-
-	"github.com/eknkc/amber"
-	"github.com/spf13/hugo/helpers"
-)
-
-func Gt(a interface{}, b interface{}) bool {
-	var left, right int64
-	av := reflect.ValueOf(a)
-
-	switch av.Kind() {
-	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
-		left = int64(av.Len())
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		left = av.Int()
-	case reflect.String:
-		left, _ = strconv.ParseInt(av.String(), 10, 64)
-	}
-
-	bv := reflect.ValueOf(b)
-
-	switch bv.Kind() {
-	case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
-		right = int64(bv.Len())
-	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-		right = bv.Int()
-	case reflect.String:
-		right, _ = strconv.ParseInt(bv.String(), 10, 64)
-	}
-
-	return left > right
-}
-
-// First is exposed to templates, to iterate over the first N items in a
-// rangeable list.
-func First(limit int, seq interface{}) (interface{}, error) {
-	if limit < 1 {
-		return nil, errors.New("can't return negative/empty count of items from sequence")
-	}
-
-	seqv := reflect.ValueOf(seq)
-	// this is better than my first pass; ripped from text/template/exec.go indirect():
-	for ; seqv.Kind() == reflect.Ptr || seqv.Kind() == reflect.Interface; seqv = seqv.Elem() {
-		if seqv.IsNil() {
-			return nil, errors.New("can't iterate over a nil value")
-		}
-		if seqv.Kind() == reflect.Interface && seqv.NumMethod() > 0 {
-			break
-		}
-	}
-
-	switch seqv.Kind() {
-	case reflect.Array, reflect.Slice, reflect.String:
-		// okay
-	default:
-		return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())
-	}
-	if limit > seqv.Len() {
-		limit = seqv.Len()
-	}
-	return seqv.Slice(0, limit).Interface(), nil
-}
-
-func IsSet(a interface{}, key interface{}) bool {
-	av := reflect.ValueOf(a)
-	kv := reflect.ValueOf(key)
-
-	switch av.Kind() {
-	case reflect.Array, reflect.Chan, reflect.Slice:
-		if int64(av.Len()) > kv.Int() {
-			return true
-		}
-	case reflect.Map:
-		if kv.Type() == av.Type().Key() {
-			return av.MapIndex(kv).IsValid()
-		}
-	}
-
-	return false
-}
-
-func ReturnWhenSet(a interface{}, index int) interface{} {
-	av := reflect.ValueOf(a)
-
-	switch av.Kind() {
-	case reflect.Array, reflect.Slice:
-		if av.Len() > index {
-
-			avv := av.Index(index)
-			switch avv.Kind() {
-			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
-				return avv.Int()
-			case reflect.String:
-				return avv.String()
-			}
-		}
-	}
-
-	return ""
-}
-
-func Highlight(in interface{}, lang string) template.HTML {
-	var str string
-	av := reflect.ValueOf(in)
-	switch av.Kind() {
-	case reflect.String:
-		str = av.String()
-	}
-
-	if strings.HasPrefix(strings.TrimSpace(str), "<pre><code>") {
-		str = str[strings.Index(str, "<pre><code>")+11:]
-	}
-	if strings.HasSuffix(strings.TrimSpace(str), "</code></pre>") {
-		str = str[:strings.LastIndex(str, "</code></pre>")]
-	}
-	return template.HTML(helpers.Highlight(html.UnescapeString(str), lang))
-}
-
-func SafeHtml(text string) template.HTML {
-	return template.HTML(text)
-}
-
-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),
-	}
-
-	funcMap := template.FuncMap{
-		"urlize":      helpers.Urlize,
-		"sanitizeurl": helpers.SanitizeUrl,
-		"gt":          Gt,
-		"isset":       IsSet,
-		"echoParam":   ReturnWhenSet,
-		"safeHtml":    SafeHtml,
-		"first":       First,
-		"highlight":   Highlight,
-		"add":         func(a, b int) int { return a + b },
-		"sub":         func(a, b int) int { return a - b },
-		"div":         func(a, b int) int { return a / b },
-		"mod":         func(a, b int) int { return a % b },
-		"mul":         func(a, b int) int { return a * b },
-		"modBool":     func(a, b int) bool { return a%b == 0 },
-		"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) },
-	}
-
-	templates.Funcs(funcMap)
-
-	templates.LoadEmbedded()
-	return templates
-}
-
-func (t *GoHtmlTemplate) LoadEmbedded() {
-	t.EmbedShortcodes()
-	t.EmbedTemplates()
-}
-
-func (t *GoHtmlTemplate) AddInternalTemplate(prefix, name, tpl string) error {
-	return t.AddTemplate("_internal/"+prefix+"/"+name, tpl)
-}
-
-func (t *GoHtmlTemplate) AddInternalShortcode(name, content string) error {
-	return t.AddInternalTemplate("shortcodes", name, content)
-}
-
-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
-	}
-	return t.AddTemplate(name, string(b))
-}
-
-func (t *GoHtmlTemplate) generateTemplateNameFrom(base, path string) string {
-	return filepath.ToSlash(path[len(base)+1:])
-}
-
-func ignoreDotFile(path string) bool {
-	return filepath.Base(path)[0] == '.'
-}
-
-func (t *GoHtmlTemplate) loadTemplates(absPath string, prefix string) {
-	walker := func(path string, fi os.FileInfo, err error) error {
-		if err != nil {
-			return nil
-		}
-
-		if !fi.IsDir() {
-			if ignoreDotFile(path) {
-				return nil
-			}
-
-			tplName := t.generateTemplateNameFrom(absPath, path)
-
-			if prefix != "" {
-				tplName = strings.Trim(prefix, "/") + "/" + tplName
-			}
-
-			// TODO move this into the AddTemplateFile function
-			if strings.HasSuffix(path, ".amber") {
-				compiler := amber.New()
-				// Parse the input file
-				if err := compiler.ParseFile(path); err != nil {
-					return nil
-				}
-
-				if _, err := compiler.CompileWithTemplate(t.New(tplName)); err != nil {
-					return err
-				}
-
-			} else {
-				t.AddTemplateFile(tplName, path)
-			}
-		}
-		return nil
-	}
-
-	filepath.Walk(absPath, walker)
-}
-
-func (t *GoHtmlTemplate) LoadTemplatesWithPrefix(absPath string, prefix string) {
-	t.loadTemplates(absPath, prefix)
-}
-
-func (t *GoHtmlTemplate) LoadTemplates(absPath string) {
-	t.loadTemplates(absPath, "")
-}
--- a/template/bundle/template_test.go
+++ /dev/null
@@ -1,55 +1,0 @@
-package bundle
-
-import (
-	"reflect"
-	"testing"
-)
-
-func TestGt(t *testing.T) {
-	for i, this := range []struct {
-		left          interface{}
-		right         interface{}
-		leftShouldWin bool
-	}{
-		{5, 8, false},
-		{8, 5, true},
-		{5, 5, false},
-		{-2, 1, false},
-		{2, -5, true},
-		{"8", "5", true},
-		{"5", "0001", true},
-		{[]int{100, 99}, []int{1, 2, 3, 4}, false},
-	} {
-		leftIsBigger := Gt(this.left, this.right)
-		if leftIsBigger != this.leftShouldWin {
-			var which string
-			if leftIsBigger {
-				which = "expected right to be bigger, but left was"
-			} else {
-				which = "expected left to be bigger, but right was"
-			}
-			t.Errorf("[%d] %v compared to %v: %s", i, this.left, this.right, which)
-		}
-	}
-}
-
-func TestFirst(t *testing.T) {
-	for i, this := range []struct {
-		count    int
-		sequence interface{}
-		expect   interface{}
-	}{
-		{2, []string{"a", "b", "c"}, []string{"a", "b"}},
-		{3, []string{"a", "b"}, []string{"a", "b"}},
-		{2, []int{100, 200, 300}, []int{100, 200}},
-	} {
-		results, err := First(this.count, this.sequence)
-		if err != nil {
-			t.Errorf("[%d] failed: %s", i, err)
-			continue
-		}
-		if !reflect.DeepEqual(results, this.expect) {
-			t.Errorf("[%d] First %d items, got %v but expected %v", i, this.count, results, this.expect)
-		}
-	}
-}