diff --git a/site/site.go b/site/site.go index d638d27..e56d7ee 100644 --- a/site/site.go +++ b/site/site.go @@ -123,8 +123,10 @@ func (site Site) Render(templ *templates.Template) (string, error) { func (site Site) baseContext() map[string]interface{} { return map[string]interface{}{ - "config": site.config, - "posts": site.posts, - "tags": site.tags, + "site": map[string]interface{}{ + "config": site.config, + "posts": site.posts, + "tags": site.tags, + }, } } diff --git a/site/site_test.go b/site/site_test.go new file mode 100644 index 0000000..db878dd --- /dev/null +++ b/site/site_test.go @@ -0,0 +1,161 @@ +package site + +import ( + "os" + "path/filepath" + "testing" +) + +func TestLoadAndRenderTemplates(t *testing.T) { + root, src, layouts := newProject() + defer os.RemoveAll(root) + + // add two layouts + content := `--- +--- + +{{page.title}} + +{{content}} + +` + file := newFile(layouts, "base.html", content) + defer os.Remove(file.Name()) + + content = `--- +layout: base +--- +

{{page.title}}

+

{{page.subtitle}}

+{{content}}` + file = newFile(layouts, "post.html", content) + defer os.Remove(file.Name()) + + // add two posts + content = `--- +layout: post +title: hello world! +subtitle: my first post +date: 2024-01-01 +--- +

Hello world!

` + file = newFile(src, "hello.html", content) + defer os.Remove(file.Name()) + + content = `--- +layout: post +title: goodbye! +subtitle: my last post +date: 2024-02-01 +--- +

goodbye world!

` + file = newFile(src, "goodbye.html", content) + defer os.Remove(file.Name()) + + // add a page (no date) + content = `--- +layout: base +title: about +--- +

about this site

` + file = newFile(src, "about.html", content) + defer os.Remove(file.Name()) + + // add a static file (no front matter) + content = `go away!` + file = newFile(src, "robots.txt", content) + + site, err := Load(src, layouts) + + assertEqual(t, err, nil) + + assertEqual(t, len(site.posts), 2) + assertEqual(t, len(site.pages), 1) + assertEqual(t, len(site.layouts), 2) + + _, ok := site.layouts["base"] + assert(t, ok) + _, ok = site.layouts["post"] + assert(t, ok) + + hello := site.posts[1] + content, err = site.Render(&hello) + assertEqual(t, err, nil) + assertEqual(t, content, ` +hello world! + +

hello world!

+

my first post

+

Hello world!

+ +`) + + goodbye := site.posts[0] + content, err = site.Render(&goodbye) + assertEqual(t, err, nil) + assertEqual(t, content, ` +goodbye! + +

goodbye!

+

my last post

+

goodbye world!

+ +`) + + about := site.pages[0] + content, err = site.Render(&about) + assertEqual(t, err, nil) + assertEqual(t, content, ` +about + +

about this site

+ +`) + +} + +func TestRenderArchive(t *testing.T) { + // TODO +} + +func TestRenderTags(t *testing.T) { + // TODO +} + +func TestRenderDataFile(t *testing.T) { + // TODO +} + +// ------ HELPERS -------- + +func newProject() (string, string, string) { + projectDir, _ := os.MkdirTemp("", "root") + layoutsDir := filepath.Join(projectDir, "layouts") + srcDir := filepath.Join(projectDir, "src") + os.Mkdir(layoutsDir, 0777) + os.Mkdir(filepath.Join(projectDir, "src"), 0777) + + return projectDir, layoutsDir, srcDir +} + +func newFile(dir string, filename string, contents string) *os.File { + path := filepath.Join(dir, filename) + file, _ := os.Create(path) + file.WriteString(contents) + return file +} + +// TODO move to assert package +func assert(t *testing.T, cond bool) { + t.Helper() + if !cond { + t.Fatalf("%v is false", cond) + } +} + +func assertEqual(t *testing.T, a interface{}, b interface{}) { + t.Helper() + if a != b { + t.Fatalf("%v != %v", a, b) + } +} diff --git a/templates/templates.go b/templates/templates.go index c21cff9..20f7b2f 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -87,8 +87,14 @@ func (templ Template) Render(context map[string]interface{}) (string, error) { // now read the proper template contents to memory contents := "" + isFirstLine := true for scanner.Scan() { - contents += scanner.Text() + "\n" + if isFirstLine { + isFirstLine = false + contents = scanner.Text() + } else { + contents += "\n" + scanner.Text() + } } if strings.HasSuffix(templ.SrcPath, ".org") { diff --git a/templates/templates_test.go b/templates/templates_test.go index 0b8d4a3..8346325 100644 --- a/templates/templates_test.go +++ b/templates/templates_test.go @@ -29,7 +29,7 @@ tags: ["software", "web"] content, err := templ.Render(nil) assertEqual(t, err, nil) - assertEqual(t, string(content), "

Hello World!

\n") + assertEqual(t, string(content), "

Hello World!

") } func TestNonTemplate(t *testing.T) { @@ -96,8 +96,7 @@ tags: ["software", "web"]

{{ page.subtitle }}

-` +` file := newFile("test*.html", input) defer os.Remove(file.Name()) @@ -112,8 +111,7 @@ tags: ["software", "web"] -` +` assertEqual(t, string(content), expected) } @@ -161,65 +159,6 @@ my Subtitle assertEqual(t, string(content), expected) } -func TestRenderLiquidLayout(t *testing.T) { - // input := `--- - // title: base layout - // --- - // - // - // - //

this is the {{layout.title}} that wraps the content of {{ page.title}}

- // {{ content }} - // - // - // ` - - // base := newFile("layouts/base*.html", input) - // defer os.Remove(base.Name()) - // baseTempl, err := Parse(base.Name()) - // assertEqual(t, err, nil) - - // context := map[string]interface{}{ - // "layouts": map[string]Template{ - // "base": *baseTempl, - // }, - // } - - // input = `--- - // title: my very first post - // layout: base - // date: 2023-12-01 - // --- - //

{{page.title}}

` - - // post := newFile("src/post1*.html", input) - // defer os.Remove(post.Name()) - - // templ, err := Parse(post.Name()) - // assertEqual(t, err, nil) - // content, err := templ.Render(context) - // assertEqual(t, err, nil) - // expected := ` - // - // - //

this is the base layout that wraps the content of my very first post

- //

my very first post

- - // - // - // ` - // - // assertEqual(t, string(content), expected) -} - -func TestRenderOrgLayout(t *testing.T) { - // TODO -} - -func TestRenderLayoutLayout(t *testing.T) { - // TODO -} - // ------ HELPERS -------- func newFile(path string, contents string) *os.File {