From 266c14c798cdbb3453cb8d3db25c2158cd1567eb Mon Sep 17 00:00:00 2001 From: Oliver Steele Date: Wed, 5 Jul 2017 12:44:38 -0400 Subject: [PATCH] Implement site.{pages,static_files,documents} --- README.md | 21 +++--- filters/filters.go | 1 + pages/drops.go | 11 ++- site/drop.go | 7 +- site/drop_test.go | 69 +++++++++++++++++++ site/site.go | 23 ++++++- site/testdata/site1/_coll1/coll1_page.md | 2 + site/testdata/site1/_coll2/coll2_page.md | 2 + site/testdata/site1/_config.yml | 5 ++ site/testdata/site1/_posts/2017-07-05-post.md | 2 + site/testdata/site1/static.html | 1 + 11 files changed, 129 insertions(+), 15 deletions(-) create mode 100644 site/drop_test.go create mode 100644 site/testdata/site1/_coll1/coll1_page.md create mode 100644 site/testdata/site1/_coll2/coll2_page.md create mode 100644 site/testdata/site1/_config.yml create mode 100644 site/testdata/site1/_posts/2017-07-05-post.md create mode 100644 site/testdata/site1/static.html diff --git a/README.md b/README.md index 02efa55..db64d36 100644 --- a/README.md +++ b/README.md @@ -40,15 +40,21 @@ gojekyll help build ## Limitations - Missing features: - - themes, page tags, excerpts, plugins (except for a few listed below), pagination, math, warning mode. - - Site variables: `pages`, `static_files`, `html_pages`, `html_files`, `documents`, and `tags` - - Jekyll filters: `group_by_exp`, `pop`, `shift`, `cgi_escape`, `uri_escape`, `scssify`, and `smartify`. - - See the [Liquid README](https://github.com/osteele/liquid/#status) for documentation of its limitations. - - Data files must be YAML. CSV and JSON data files are not supported. + - Themes + - Excerpts + - Pagination + - Math + - Warning mode + - Plugins, except `jekyll-avatar` and `jekyll-gist` + - Site variables: `html_pages`, `html_files`, and `tags` + - Jekyll filters: `group_by_exp`, `pop`, `shift`, `cgi_escape`, `uri_escape`, `scssify`, and `smartify` + - Some Liquid features. See [Go Liquid README](https://github.com/osteele/liquid/#status). + - CSV and JSON data files. - `{% highlight %}` uses Pygments. There's no way to tell it to use Rouge. Also, I don't know what will happen if Pygments isn't installed. - `
` doesn't work. I think this is a limitation of the Blackfriday Markdown processor. -- This is a new code base. It probably panics or otherwise fails on a lot of legitimate constructs, and misbehaves on others. +- This is a very new code base. It probably panics or otherwise fails on a lot of legitimate constructs, and misbehaves on others. - Liquid errors aren't reported very nicely. +- `build` with no `-d` option resolves the destination relative to the source directory, not the current directory. ## Other Differences @@ -58,8 +64,7 @@ These will probably not change. - Files are cached to `/tmp/gojekyll-${USER}`, not `./.sass-cache` - Server live reload is always on. - The server reloads the `_config.yml` (and the rest of the site) when that file changes. -- `build` with no `-d` option resolves the destination relative to the source directory, not the current directory. -- Some plugins are built into the executable. Others may be added. There's no an extensible plugin mechanism in the near-to-medium future. +- An extensible plugin mechanism. Emulations of commonly-used plugins can be added to the repo. ## Timings diff --git a/filters/filters.go b/filters/filters.go index f42d06f..86cc83b 100644 --- a/filters/filters.go +++ b/filters/filters.go @@ -209,6 +209,7 @@ func sortFilter(array []interface{}, key interface{}, nilFirst interface{}) []in if key == nil { evaluator.Sort(out) } else { + // TODO error if key is not a string evaluator.SortByProperty(out, key.(string), nf) } return out diff --git a/pages/drops.go b/pages/drops.go index 92270e6..11b1ca0 100644 --- a/pages/drops.go +++ b/pages/drops.go @@ -8,8 +8,15 @@ import ( "github.com/osteele/gojekyll/templates" ) -// ToLiquid returns the attributes of the template page object. -// See https://jekyllrb.com/docs/variables/#page-variables +// ToLiquid is part of the liquid.Drop interface. +func (d *StaticFile) ToLiquid() interface{} { + return map[string]interface{}{ + "path": d.Path(), // TODO is this the absolute or relative path? + "modified_time": d.fileModTime, + "extname": d.OutputExt(), + } +} + func (f *file) ToLiquid() interface{} { var ( relpath = "/" + filepath.ToSlash(f.relpath) diff --git a/site/drop.go b/site/drop.go index 9a5addf..8abf688 100644 --- a/site/drop.go +++ b/site/drop.go @@ -29,10 +29,13 @@ func (s *Site) MarshalYAML() (interface{}, error) { func (s *Site) initializeDrop() { vars := templates.MergeVariableMaps(s.config.Variables, map[string]interface{}{ - "data": s.data, + "data": s.data, + "documents": s.docs, // "collections": s.computeCollections(), // generics.MustConvert(s.config.Collections, reflect.TypeOf([]interface{}{})), // TODO read time from _config, if it's available - "time": time.Now(), + "time": time.Now(), + "pages": s.Pages(), + "static_files": s.StaticFiles(), // TODO pages, static_files, html_pages, html_files, documents, tags.TAG }) collections := []interface{}{} diff --git a/site/drop_test.go b/site/drop_test.go new file mode 100644 index 0000000..70a845d --- /dev/null +++ b/site/drop_test.go @@ -0,0 +1,69 @@ +package site + +import ( + "fmt" + "testing" + "time" + + "github.com/osteele/gojekyll/config" + "github.com/osteele/gojekyll/pages" + "github.com/stretchr/testify/require" +) + +func readTestSiteDrop(t *testing.T) map[string]interface{} { + site, err := FromDirectory("testdata/site1", config.Flags{}) + require.NoError(t, err) + require.NoError(t, site.Load()) + return site.ToLiquid().(map[string]interface{}) +} + +// TODO test cases for collections, categories, tags, data + +func TestSite_ToLiquid_documents(t *testing.T) { + drop := readTestSiteDrop(t) + docs, isTime := drop["documents"].([]pages.Document) + require.True(t, isTime, fmt.Sprintf("documents has type %T", drop["documents"])) + require.Len(t, docs, 4) +} +func TestSite_ToLiquid_time(t *testing.T) { + drop := readTestSiteDrop(t) + _, ok := drop["time"].(time.Time) + require.True(t, ok) + + // TODO read time from config if present +} + +func TestSite_ToLiquid_pages(t *testing.T) { + drop := readTestSiteDrop(t) + pages, ok := drop["pages"].([]pages.Page) + require.True(t, ok, fmt.Sprintf("pages has type %T", drop["pages"])) + require.Len(t, pages, 3) +} + +func TestSite_ToLiquid_posts(t *testing.T) { + drop := readTestSiteDrop(t) + posts, ok := drop["posts"].([]pages.Page) + require.True(t, ok, fmt.Sprintf("posts has type %T", drop["posts"])) + require.Len(t, posts, 1) +} + +func TestSite_ToLiquid_related_posts(t *testing.T) { + drop := readTestSiteDrop(t) + posts, ok := drop["related_posts"].([]pages.Page) + require.True(t, ok, fmt.Sprintf("related_posts has type %T", drop["related_posts"])) + require.Len(t, posts, 1) +} + +func TestSite_ToLiquid_static_files(t *testing.T) { + drop := readTestSiteDrop(t) + files, ok := drop["static_files"].([]*pages.StaticFile) + require.True(t, ok, fmt.Sprintf("static_files has type %T", drop["static_files"])) + require.Len(t, files, 1) + + // TODO move this test to pages package + f := files[0].ToLiquid().(map[string]interface{}) + require.Equal(t, "static.html", f["path"]) + _, isTime := f["modified_time"].(time.Time) + require.True(t, isTime) + require.Equal(t, ".html", f["extname"]) +} diff --git a/site/site.go b/site/site.go index e9b7f27..6b79943 100644 --- a/site/site.go +++ b/site/site.go @@ -19,7 +19,7 @@ import ( type Site struct { ConfigFile *string Collections []*collection.Collection - Routes map[string]pages.Document // URL path -> Page, only for output pages + Routes map[string]pages.Document // URL path -> Document, only for output pages config config.Config data map[string]interface{} @@ -27,7 +27,7 @@ type Site struct { pipeline *pipelines.Pipeline docs []pages.Document // all documents, whether or not they are output preparedToRender bool - drop map[string]interface{} // cached drop value + drop map[string]interface{} // cached drop value sync.Mutex } @@ -51,8 +51,25 @@ func (s *Site) OutputPages() []pages.Document { return out } +// StaticFiles returns a list of static files. +func (s *Site) StaticFiles() (out []*pages.StaticFile) { + for _, d := range s.docs { + if sd, ok := d.(*pages.StaticFile); ok { + out = append(out, sd) + } + } + return +} + // Pages returns all the pages, output or not. -func (s *Site) Pages() []pages.Document { return s.docs } +func (s *Site) Pages() (out []pages.Page) { + for _, d := range s.docs { + if p, ok := d.(pages.Page); ok { + out = append(out, p) + } + } + return +} // AbsDir is in the collection.Site interface. func (s *Site) AbsDir() string { diff --git a/site/testdata/site1/_coll1/coll1_page.md b/site/testdata/site1/_coll1/coll1_page.md new file mode 100644 index 0000000..a845151 --- /dev/null +++ b/site/testdata/site1/_coll1/coll1_page.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/site/testdata/site1/_coll2/coll2_page.md b/site/testdata/site1/_coll2/coll2_page.md new file mode 100644 index 0000000..a845151 --- /dev/null +++ b/site/testdata/site1/_coll2/coll2_page.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/site/testdata/site1/_config.yml b/site/testdata/site1/_config.yml new file mode 100644 index 0000000..0490a33 --- /dev/null +++ b/site/testdata/site1/_config.yml @@ -0,0 +1,5 @@ +collections: + coll1: + output: true + coll2: + output: false diff --git a/site/testdata/site1/_posts/2017-07-05-post.md b/site/testdata/site1/_posts/2017-07-05-post.md new file mode 100644 index 0000000..a845151 --- /dev/null +++ b/site/testdata/site1/_posts/2017-07-05-post.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/site/testdata/site1/static.html b/site/testdata/site1/static.html new file mode 100644 index 0000000..c1ffed9 --- /dev/null +++ b/site/testdata/site1/static.html @@ -0,0 +1 @@ +static file \ No newline at end of file