diff --git a/README.md b/README.md index 2b92032..391f064 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ go get launchpad.net/goyaml go get launchpad.net/goamz/aws go get launchpad.net/goamz/s3 go get github.com/howeyc/fsnotify +go get github.com/extemporalgenome/slug ``` Once you have compiled `jkl` you can install with the following command: diff --git a/post.go b/post.go index d124bf9..5de2e13 100644 --- a/post.go +++ b/post.go @@ -6,15 +6,42 @@ import ( "path/filepath" "strings" "time" + "github.com/extemporalgenome/slug" ) var ( ErrBadPostName = errors.New("Invalid post name. Expecting format YYYY-MM-DD-name-of-post.markdown") ) +func getPostUrl(title string, date time.Time, categories []string, permalink string) (url string) { + switch permalink { + case "date": + permalink = "/:categories/:year/:month/:day/:title.html" + case "pretty": + permalink = "/:categories/:year/:month/:day/:title/" + case "none": + permalink = "/:categories/:title.html" + } + + url = permalink + url = strings.Replace(url, ":title", title, -1) + url = strings.Replace(url, ":year", fmt.Sprintf("%02d", date.Year()), -1) + url = strings.Replace(url, ":month", fmt.Sprintf("%02d", date.Month()), -1) + url = strings.Replace(url, ":i_month", fmt.Sprintf("%d", date.Month()), -1) + url = strings.Replace(url, ":day", fmt.Sprintf("%02d", date.Day()), -1) + url = strings.Replace(url, ":i_day", fmt.Sprintf("%d", date.Day()), -1) + + for i, value := range categories { + categories[i] = slug.Slug(value) + } + url = strings.Replace(url, ":categories", strings.Join(categories, "/"), -1) + url = strings.Replace(url, "//", "/", -1) + return url +} + // ParseParse will parse a file with front-end YAML and markup content, and // return a key-value Post structure. -func ParsePost(fn string) (Page, error) { +func ParsePost(fn string, permalink string) (Page, error) { post, err := ParsePage(fn) if err != nil { return nil, err @@ -34,13 +61,9 @@ func ParsePost(fn string) (Page, error) { post["title"] = t } - // figoure out the Posts permalink - mon := fmt.Sprintf("%02d", d.Month()) - day := fmt.Sprintf("%02d", d.Day()) - year := fmt.Sprintf("%02d", d.Year()) - name := replaceExt(f, ".html") - post["id"] = filepath.Join(year, mon, day, f) // TODO try to remember why I need this field - post["url"]= filepath.Join(year, mon, day, name[11:]) + // Figure out the Posts permalink + title := replaceExt(f, "")[11:] + post["url"] = getPostUrl(title, d, post.GetCategories(), permalink) return post, nil } diff --git a/post_test.go b/post_test.go new file mode 100644 index 0000000..9ae89be --- /dev/null +++ b/post_test.go @@ -0,0 +1,171 @@ +package main + +import ( + "testing" + "time" +) + +func TestPermalinkTitle(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-11") + url := getPostUrl("my-blog", date, []string{}, "/:title/") + + if (url != "/my-blog/") { + t.Errorf("Expected url [/my-blog/] got [%s]", url) + } +} + +func TestPermalinkYear(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-11") + url := getPostUrl("my-blog", date, []string{}, "/:year/") + + if (url != "/2013/") { + t.Errorf("Expected url [/2013/] got [%s]", url) + } +} + +func TestPermalinkMonth(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-11") + url := getPostUrl("my-blog", date, []string{}, "/:month/") + + if (url != "/11/") { + t.Errorf("Expected url [/11/] got [%s]", url) + } +} + +func TestPermalinkMonthWithOneDigitMonth(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-02-11") + url := getPostUrl("my-blog", date, []string{}, "/:month/") + + if (url != "/02/") { + t.Errorf("Expected url [/02/] got [%s]", url) + } +} + +func TestPermalinkIMonth(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + url := getPostUrl("my-blog", date, []string{}, "/:i_month/") + + if (url != "/11/") { + t.Errorf("Expected url [/11/] got [%s]", url) + } +} + +func TestPermalinkIMonthWithOneDigit(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-02-01") + url := getPostUrl("my-blog", date, []string{}, "/:i_month/") + + if (url != "/2/") { + t.Errorf("Expected url [/2/] got [%s]", url) + } +} + +func TestPermalinkDay(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-25") + url := getPostUrl("my-blog", date, []string{}, "/:day/") + + if (url != "/25/") { + t.Errorf("Expected url [/25/] got [%s]", url) + } +} + +func TestPermalinkDayWithOneDigit(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + url := getPostUrl("my-blog", date, []string{}, "/:day/") + + if (url != "/01/") { + t.Errorf("Expected url [/01/] got [%s]", url) + } +} + + +func TestPermalinkIDay(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-25") + url := getPostUrl("my-blog", date, []string{}, "/:i_day/") + + if (url != "/25/") { + t.Errorf("Expected url [/25/] got [%s]", url) + } +} + +func TestPermalinkIDayWithOneDigit(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + url := getPostUrl("my-blog", date, []string{}, "/:i_day/") + + if (url != "/1/") { + t.Errorf("Expected url [/1/] got [%s]", url) + } +} + +func TestSingleCategory(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + categories := []string{"My Category"} + url := getPostUrl("my-blog", date, categories, "/:categories/index.html") + + if (url != "/my-category/index.html") { + t.Errorf("Expected url [/my-category/index.html] got [%s]", url) + } +} + +func TestMultipleCategories(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + categories := []string{"Go Lang", "Unit Testing"} + url := getPostUrl("my-blog", date, categories, "/:categories/index.html") + + if (url != "/go-lang/unit-testing/index.html") { + t.Errorf("Expected url [/go-lang/unit-testing/index.html] got [%s]", url) + } +} + +func TestEmptyCategories(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + categories := []string{} + url := getPostUrl("my-blog", date, categories, "/:categories/:title/") + + if (url != "/my-blog/") { + t.Errorf("Expected url [/my-blog/] got [%s]", url) + } +} + +func TestUnicodeCategories(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + categories := []string{"áãàâäçéèëíìïóòôöúùûü"} + url := getPostUrl("my-blog", date, categories, "/:categories/:title/") + + if (url != "/aaaaaceeeiiioooouuuu/my-blog/") { + t.Errorf("Expected url [/my-blog/] got [%s]", url) + } +} + + +// The 'date' permalink is a shortcut to /:categories/:year/:month/:day/:title.html +func TestDateBuiltinPermakink(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + categories := []string{"go"} + url := getPostUrl("unit-tests", date, categories, "date") + + if (url != "/go/2013/11/01/unit-tests.html") { + t.Errorf("Expected url [/go/2013/11/01/unit-tests.html] got [%s]", url) + } +} + +// The 'pretty' permalink is a shortcut to /:categories/:year/:month/:day/:title/ +func TestPrettyBuiltinPermakink(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + categories := []string{"go"} + url := getPostUrl("unit-tests", date, categories, "pretty") + + if (url != "/go/2013/11/01/unit-tests/") { + t.Errorf("Expected url [/go/2013/11/01/unit-tests/] got [%s]", url) + } +} + +// The 'none' permalink is a shortcut to /:categories/:title.html +func TestNoneBuiltinPermakink(t *testing.T) { + date, _ := time.Parse("2006-01-02", "2013-11-01") + categories := []string{"go"} + url := getPostUrl("unit-tests", date, categories, "none") + + if (url != "/go/unit-tests.html") { + t.Errorf("Expected url [/go/unit-tests.html] got [%s]", url) + } +} diff --git a/site.go b/site.go index ea3fb25..2271aaa 100644 --- a/site.go +++ b/site.go @@ -9,6 +9,7 @@ import ( "mime" "os" "path/filepath" + "strings" "text/template" "time" ) @@ -162,7 +163,14 @@ func (s *Site) read() error { // Parse Posts case isPost(rel): - post, err := ParsePost(rel) + permalink := s.Conf.GetString("permalink") + if (permalink == "") { + // According to Jekyll documentation 'date' is the + // default permalink + permalink = "date" + } + + post, err := ParsePost(rel, permalink) if err != nil { return err } @@ -221,6 +229,9 @@ func (s *Site) writePages() error { for _, page := range pages { url := page.GetUrl() + if (strings.HasSuffix(url, "/")) { + url += "index.html" + } layout := page.GetLayout() // is the layout provided? or is it nil /empty?