Node.Site.Recent is not really just recent pages, but all pages, so I figured it was better to add a new parameter with a more informative name.
I also changed the code slightly so that all pages are added to the list of pages before we start rendering shortcodes... this way you can use a shortcode to refer to another page. Previosuly, this had been broken, because the list ofg pages would not be fully populated while the shortcodes were being processed. The code that does this is not reading from disk or doing any rendering, so it shouldn't take any more time to do.
This fixes#450. There are two problems:
1.) We're creating a new goroutine for every page.
2.) We're calling s.Pages = append(s.Pages, page) inside each goroutine.
1 is a problem if in that if you have a ton of pages, that's a ton of goroutines. It's not really useful to have more than a few goroutines at a time, and lots can actually make your code much slower, and, evidently, crash.
2 is a problem in that append is not thread safe. Sometimes it returns a new slice with a larger capacity, when the original slice isn't large enough. This can cause problems if two goroutines do this at the same time.
The solution for 1 is to use a limited number of workers (I chose 2*GOMAXPROCS as a nice guess).
The solution for 2 is to serialize access to s.Pages, which I did by doing it in a single goroutine.
Mainly this was a change to helpers.MakePermalink, but to get the local server to run correctly,
we needed to redirect the path of the request from /foo to /. In addition, I added tests for the
server's code for fixing up the base url with different config file & CLI options.
git bisect identified 62dd1d4 as the breaking commit; when
github.com/spf13/viper was introduced, the Params field was always
empty.
Given a map in YAML in Viper, the return type is
`map[interface{}]interface{}`, _not_ `map[string]interface{}`, even if
`.SetDefault()` has been called with an item of
`map[string]interface{}{}` so the cast assertion on the `.Get("Params")`
always failed.
Viper stores Permalinks as a map[string]interface{}, so the type assertion
to PermalinkOverrides (map[string]PathPattern) will always fail.
We can, however, get Permalinks as a map[string]string, and convert each
value to a PathPattern.