shannonmoeller/handlebars-layouts — pull request #5 by idpaterson (2014-05-30 15:40:15+00:00)
Title: Support for programmatically composed layouts

I wanted to use the Handlebars Layouts helpers, but they did not work with the layout system that I was using, [express3-handlebars](/ericf/express3-handlebars). Rather than allowing views to specify a layout by name, the layout is specified either in the global express3-handlebars configuration or on a per-render basis. The module compiles the view into an HTML string, then renders the layout, providing the body such that the layout can show it with `{{{body}}}`. Clearly this is not as powerful as Handlebars Layouts.

This very simple change allows the `append`, `prepend`, and `replace` blocks to be used outside of an `extend` block by initializing `context._blocks = {}` if it does not yet exist. `_blocks` is still maintained on the context allowing the layout, compiled with the same context or at least with a copy of the `_blocks` attribute, to define modifiable blocks.

### Tests

I added three test cases to hopefully cover the gamut of potential use cases for this.
1. `should properly render programmatically-composed layouts` tests that the approach described above of rendering the view to a string and then passing that to the body. The test uses `{{#block "body"}}` rather than `{{{body}}}` since it is a more useful pattern.
2. `should properly render self-modifying layouts` might be useful in limited circumstances, such as providing top-of-file configuration blocks for a very large and gangly template.
3. `should properly render layouts included as partials` exists only to test that including the template as a partial works. There is no reason I can think of to not use an `extend` block in this case so I noted that in the template comments.

### Caveats

This requires either the same context to be used when rendering the layout, or the `_blocks` attribute to be copied. `express3-handlebars` does this already by extending the context used for the view to add a property to the rendered view `{body: body}`, preserving `_blocks`. I do not know whether other layout engines that may also benefit from this change do the same so I added a note to that effect in the readme.