Skip to content

Commit

Permalink
bring in dependency for decoding front matter & re-use it for configu…
Browse files Browse the repository at this point in the history
…ration file
  • Loading branch information
dannyvankooten committed Nov 24, 2023
1 parent ffcbe2a commit 8cee5ed
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 73 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ You can create this structure by running `gozer new`.
content/ # Your posts and pages
templates/ # Your Go templates
public/ # Any static files
config.xml # Configuration file
config.toml # Configuration file
```

Placing Markdown files in your `content/` directory will create a page in your build directory after running `gozer build`.
Expand All @@ -48,12 +48,12 @@ Commands:
Options:
-r, --root <ROOT> Directory to use as root of project (default: .)
-c, --config <CONFIG> Path to configuration file (default: config.xml)
-c, --config <CONFIG> Path to configuration file (default: config.toml)
```

## Content files

Each file in your `content/` directory should end in `.md` and have front matter specifying the page title:
Each file in your `content/` directory should end in `.md` and have TOML front matter specifying the page title:

```md
+++
Expand Down
2 changes: 2 additions & 0 deletions example/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
url = "http://localhost:8080"
title = "My website"
3 changes: 0 additions & 3 deletions example/config.xml

This file was deleted.

1 change: 1 addition & 0 deletions example/content/2023-11-01-hello-world.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
+++
title = "Hello, world!"
foo = "Bar"
+++

This is a blog post.
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ module github.com/dannyvankooten/gozer
go 1.21.4

require github.com/yuin/goldmark v1.6.0

require github.com/BurntSushi/toml v1.3.2 // indirect
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
Expand Down
91 changes: 35 additions & 56 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"errors"
"flag"
"fmt"
"github.com/BurntSushi/toml"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/renderer/html"
"html/template"
Expand All @@ -33,8 +34,13 @@ var templates *template.Template
//go:embed sitemap.xsl
var sitemapXSL []byte

type Config struct {
SiteUrl string `xml:"site_url"`
type Site struct {
pages []Page
posts []Page

Title string `toml:"title"`
SiteUrl string `toml:"url"`
RootDir string
}

type Page struct {
Expand All @@ -51,6 +57,7 @@ type Page struct {
func parseFilename(path string, rootDir string) (string, time.Time) {
path = strings.TrimPrefix(path, rootDir+"content/")
path = strings.TrimSuffix(path, ".md")
path = strings.TrimSuffix(path, ".html")
path = strings.TrimSuffix(path, "index")

filename := filepath.Base(path)
Expand Down Expand Up @@ -81,36 +88,22 @@ func parseFrontMatter(p *Page) error {
return errors.New("missing front matter")
}

var fm bytes.Buffer

for scanner.Scan() {
line := scanner.Text()
line := scanner.Bytes()

// quit if at end of front matter
if line == string(frontMatter) {
if bytes.Equal(line, frontMatter) {
break
}

pos := strings.Index(line, "=")
if pos == -1 {
continue
}

name := strings.TrimSpace(line[0:pos])
value := strings.TrimSpace(line[pos+1:])
if value[0] == '"' {
value = strings.Trim(value, "\"")
}

switch name {
case "title":
p.Title = value
case "template":
p.Template = value
case "date":
// discard, we get this from filename only now
default:
log.Warn("Unknown front-matter key in %s: %#v\n", p.Filepath, name)
}
fm.Write(line)
fm.Write([]byte("\n"))
}

if _, err := toml.Decode(fm.String(), p); err != nil {
return err
}

return nil
Expand Down Expand Up @@ -173,14 +166,6 @@ func (s *Site) buildPage(p *Page) error {
})
}

type Site struct {
pages []Page
posts []Page

SiteUrl string
RootDir string
}

func (s *Site) AddPageFromFile(file string) error {
info, err := os.Stat(file)
if err != nil {
Expand Down Expand Up @@ -357,24 +342,20 @@ func (s *Site) createRSSFeed() error {
return nil
}

func parseConfig(file string) (*Config, error) {
wr, err := os.Open(file)
func parseConfig(s *Site, file string) error {
_, err := toml.DecodeFile(file, s)
if err != nil {
return nil, err
}
defer wr.Close()
var config Config
if err := xml.NewDecoder(wr).Decode(&config); err != nil {
return nil, err
return err
}

config.SiteUrl = strings.TrimSuffix(config.SiteUrl, "/") + "/"
// ensure site url has trailing slash
s.SiteUrl = strings.TrimSuffix(s.SiteUrl, "/") + "/"

return &config, nil
return nil
}

func main() {
configFile := "config.xml"
configFile := "config.toml"
rootPath := ""

// parse flags
Expand All @@ -397,7 +378,7 @@ Commands:
Options:
-r, --root <ROOT> Directory to use as root of project (default: .)
-c, --config <CONFIG> Path to configuration file (default: config.xml)
-c, --config <CONFIG> Path to configuration file (default: config.toml)
`)
return
}
Expand All @@ -423,6 +404,7 @@ Options:
}

func createDirectoryStructure(rootPath string) error {

if err := os.Mkdir(rootPath+"content", 0755); err != nil {
return err
}
Expand All @@ -433,12 +415,12 @@ func createDirectoryStructure(rootPath string) error {
return err
}

// create config.xml
fh, err := os.Create(rootPath + "config.xml")
// create configuration file
fh, err := os.Create(rootPath + "config.toml")
if err != nil {
return err
}
_, _ = fh.WriteString("<config>\n\t<site_url>http://localhost:8080</site_url>\n</config>")
_, _ = fh.Write([]byte("url = \"http://localhost:8080\"\ntitle = \"My website\"\n"))
fh.Close()

// create default template
Expand All @@ -450,7 +432,7 @@ func createDirectoryStructure(rootPath string) error {
fh.Close()

// create homepage
fh, err = os.Create(rootPath + "content/index.html")
fh, err = os.Create(rootPath + "content/index.md")
if err != nil {
return err
}
Expand All @@ -470,15 +452,12 @@ func buildSite(rootPath string, configFile string) {
}

// read config.xml
var config *Config
config, err = parseConfig(rootPath + configFile)
if err != nil {
log.Fatal("Error reading configuration file at %s: %w\n", rootPath+configFile, err)
site := &Site{
RootDir: rootPath,
}

site := Site{
SiteUrl: config.SiteUrl,
RootDir: rootPath,
if err := parseConfig(site, rootPath+configFile); err != nil {
log.Fatal("Error reading configuration file at %s: %w\n", rootPath+configFile, err)
}

// read content
Expand Down
51 changes: 40 additions & 11 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,28 @@ import (

func TestExampleSite(t *testing.T) {
_ = os.RemoveAll("build/")
buildSite("example/", "config.xml")
buildSite("example/", "config.toml")

tests := []struct {
file string
contains []byte
contains [][]byte
}{
{"index.html", []byte("<p>Hey, welcome on my site!</p>")},
{"about/index.html", []byte("<li>Dolor</li>")},
{"hello-world/index.html", []byte("This is a blog post.")},
{"favicon.ico", []byte{}},
{"feed.xml", []byte{}},
{"sitemap.xml", []byte("<url><loc>http://localhost:8080//</loc>")},
{"sitemap.xsl", []byte{}},
{"index.html", [][]byte{
[]byte("<p>Hey, welcome on my site!</p>"),
[]byte("<title>My site</title>")},
},
{"about/index.html", [][]byte{
[]byte("<title>About me</title>"),
[]byte("<li>Dolor</li>")},
},
{"hello-world/index.html", [][]byte{
[]byte("<title>Hello, world!</title>"),
[]byte("This is a blog post.")},
},
{"favicon.ico", nil},
{"feed.xml", nil},
{"sitemap.xml", [][]byte{[]byte("<url><loc>http://localhost:8080//</loc>")}},
{"sitemap.xsl", nil},
}

for _, tc := range tests {
Expand All @@ -30,9 +39,29 @@ func TestExampleSite(t *testing.T) {
t.Errorf("Expected file, got error: %s", err)
}

if !bytes.Contains(content, tc.contains) {
t.Errorf("Output file %s does not have expected content %s", tc.file, tc.contains)
for _, e := range tc.contains {
if !bytes.Contains(content, e) {
t.Errorf("Output file %s does not have expected content %s", tc.file, e)
}
}

}
}

func TestParseConfigFile(t *testing.T) {
s := Site{}
if err := parseConfig(&s, "example/config.toml"); err != nil {
t.Errorf("error parsing config file: %s", err)
}

expectedSiteUrl := "http://localhost:8080/"
expectedTitle := "My website"
if s.SiteUrl != expectedSiteUrl {
t.Errorf("invalid site url. expected %v, got %v", expectedSiteUrl, s.SiteUrl)
}

if s.Title != expectedTitle {
t.Errorf("invalid site title. expected %v, got %v", expectedTitle, s.Title)
}
}

Expand Down

0 comments on commit 8cee5ed

Please sign in to comment.