diff options
| author | Nicolas Paul <n@nc0.fr> | 2023-04-25 18:38:38 +0200 |
|---|---|---|
| committer | Nicolas Paul <n@nc0.fr> | 2023-04-25 18:38:38 +0200 |
| commit | 5b124812414fed3335ebb6ede394a656e9d1056a (patch) | |
| tree | cad64e14808112b8f63386929fbf2c5497ebf48e | |
| parent | a9fee8efcff4d279eb646c603ee20b6675e1921e (diff) | |
Add front matter parsing
| -rw-r--r-- | .github/workflows/ci.yml | 2 | ||||
| -rw-r--r-- | Makefile | 5 | ||||
| -rw-r--r-- | README | 4 | ||||
| -rw-r--r-- | crocc.go | 25 | ||||
| -rw-r--r-- | frontmatter.go | 39 | ||||
| -rw-r--r-- | frontmatter_test.go | 117 | ||||
| -rw-r--r-- | go.mod | 1 | ||||
| -rw-r--r-- | go.sum | 2 |
8 files changed, 189 insertions, 6 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ebe7dde..dc914ce 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - name: Building project run: make - name: Testing project - run: go test + run: make test - name: Downloading CI dependencies run: | go install golang.org/x/tools/cmd/goimports@latest @@ -12,7 +12,10 @@ LDFLAGS := -ldflags "-w -s -X main.version=$(VERSION) -X main.date=$(DATE)" $(BINARY): *.go go build $(LDFLAGS) -o $(BINARY) +test: *.go + go test -v ./... + clean: rm -f $(BINARY) -.PHONY: clean +.PHONY: clean test @@ -90,8 +90,8 @@ Example --- title: Hello World description: This is a simple example of a Markdown document. - publication_time: 2013-01-01 - last_update_time: 2013-01-01 + publication_time: 2020-01-01T00:00:00Z + last_update_time: 2020-01-01T03:00:00Z keywords: [example, hello, world] author: John Doe hide: true @@ -7,6 +7,7 @@ package main /* import "go.nc0.fr/crocc" */ import ( "flag" + "fmt" "log" "runtime" ) @@ -45,14 +46,34 @@ func init() { } } +// versionFormat returns a string containing the build information. +func versionFormat() string { + return fmt.Sprintf("crocc version %s %s/%s %s date %s", + version, runtime.GOOS, runtime.GOARCH, runtime.Compiler, date) +} + func main() { flag.Parse() log.SetFlags(0) if *printVersion { - log.Printf("crocc version %s %s/%s %s date %s", - version, runtime.GOOS, runtime.GOARCH, runtime.Compiler, date) + log.Print(versionFormat()) return } + + inputdir := flag.Arg(0) + if inputdir == "" { + log.Fatalln("no input directory specified") + } + + if *verbose { + log.Printf(`Version: %s +Input directory: %s +Output directory: %s +Site URL: %s +Generate sitemap: %t +Generate hidden pages: %t`, versionFormat(), inputdir, *outputdir, *url, + *sitemap, *generateHidden) + } } diff --git a/frontmatter.go b/frontmatter.go new file mode 100644 index 0000000..03237b5 --- /dev/null +++ b/frontmatter.go @@ -0,0 +1,39 @@ +// Copyright (c) 2023 Nicolas Paul All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "bytes" + "time" + + "github.com/adrg/frontmatter" +) + +// FrontMatter is the front matter of a Markdown document. +type FrontMatter struct { + Title string `yaml:"title"` + Description string `yaml:"description"` + PublicationTime time.Time `yaml:"publication_time"` + LastUpdateTime time.Time `yaml:"last_update_time"` + Keywords []string `yaml:"keywords"` + Author string `yaml:"author"` + Hide bool `yaml:"hide"` +} + +// ParseFrontMatter parses the front matter of a Markdown document. +// It returns a FrontMatter struct and the Markdown document without the +// front matter. +func ParseFrontMatter(r []byte) (FrontMatter, []byte, error) { + var fm FrontMatter + + reader := bytes.NewReader(r) + + rest, err := frontmatter.MustParse(reader, &fm) + if err != nil { + return FrontMatter{}, nil, err + } + + return fm, rest, nil +} diff --git a/frontmatter_test.go b/frontmatter_test.go new file mode 100644 index 0000000..98d8164 --- /dev/null +++ b/frontmatter_test.go @@ -0,0 +1,117 @@ +// Copyright (c) 2023 Nicolas Paul All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "strconv" + "testing" + "time" + + "github.com/google/go-cmp/cmp" +) + +func TestParseFrontMatter(t *testing.T) { + tests := []struct { + input []byte + want FrontMatter + rest string + }{ + { + input: []byte(`--- +title: "Test" +description: "Test" +publication_time: 2020-01-01T00:00:00Z +last_update_time: 2020-01-01T00:00:00Z +keywords: ["test"] +author: "Test" +hide: false +--- +# Test`), + want: FrontMatter{ + Title: "Test", + Description: "Test", + PublicationTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + LastUpdateTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + Keywords: []string{"test"}, + Author: "Test", + Hide: false, + }, + rest: "# Test", + }, + { + input: []byte(`--- +title: "Test" +description: "Test" +publication_time: 2020-01-01T00:00:00Z +keywords: ["test", "test2", "test3"] +--- +# Test`), + want: FrontMatter{ + Title: "Test", + Description: "Test", + PublicationTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + Keywords: []string{"test", "test2", "test3"}, + }, + rest: "# Test", + }, + } + + for _, tt := range tests { + fm, rest, err := ParseFrontMatter(tt.input) + + if err != nil { + t.Fatalf("ParseFrontMatter(%v) got error %v", tt.input, err) + } + + if !cmp.Equal(fm, tt.want) { + t.Fatalf("ParseFrontMatter(%v) got %v want %v", tt.input, fm, tt.want) + } + + if string(rest) != tt.rest { + t.Fatalf("ParseFrontMatter(%v) got %v want %v", tt.input, rest, tt.rest) + } + } +} + +func FuzzParseFrontMatter(f *testing.F) { + // Do not fuzz *_time fields as time.Time is not supported by f.Fuzz(). + f.Fuzz(func(t *testing.T, title string, description string, keyword1 string, keyword2 string, keyword3 string, author string, hide bool, text string) { + input := []byte(`--- +title: "` + title + `" +description: "` + description + `" +publication_time: 2020-01-01T00:00:00Z +last_update_time: 2020-01-01T00:00:00Z +keywords: ["` + keyword1 + `", "` + keyword2 + `", "` + keyword2 + `"] +author: "` + author + `" +hide: ` + strconv.FormatBool(hide) + ` +--- +` + text) + + fm, rest, err := ParseFrontMatter(input) + + if err != nil { + t.Fatalf("ParseFrontMatter(%v) got error %v", input, err) + } + + if string(rest) != text { + t.Fatalf("ParseFrontMatter(%v) got %v want %v", input, rest, text) + } + + result := FrontMatter{ + Title: title, + Description: description, + Keywords: []string{keyword1, keyword2, keyword3}, + PublicationTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + LastUpdateTime: time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC), + Author: author, + Hide: hide, + } + + if !cmp.Equal(fm, result) { + t.Fatalf("ParseFrontMatter(%v) got %v want %v", input, fm, result) + } + + }) +} @@ -6,5 +6,6 @@ require ( github.com/BurntSushi/toml v0.3.1 // indirect github.com/adrg/frontmatter v0.2.0 // indirect github.com/gomarkdown/markdown v0.0.0-20230322041520-c84983bdbf2a // indirect + github.com/google/go-cmp v0.5.9 // indirect gopkg.in/yaml.v2 v2.3.0 // indirect ) @@ -4,6 +4,8 @@ github.com/adrg/frontmatter v0.2.0 h1:/DgnNe82o03riBd1S+ZDjd43wAmC6W35q67NHeLkPd github.com/adrg/frontmatter v0.2.0/go.mod h1:93rQCj3z3ZlwyxxpQioRKC1wDLto4aXHrbqIsnH9wmE= github.com/gomarkdown/markdown v0.0.0-20230322041520-c84983bdbf2a h1:AWZzzFrqyjYlRloN6edwTLTUbKxf5flLXNuTBDm3Ews= github.com/gomarkdown/markdown v0.0.0-20230322041520-c84983bdbf2a/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
