publicclass/express-partials — pull request #1 by RandomEtc (2012-05-26 08:51:41+00:00)
Title: blocks, include, inherits and caching for partials

I've attempted to implement a few features but it required a bit of rearranging to do so... I've opened this pull request to get feedback, I'll follow up with some tweaks to the README etc if reception is generally positive.

These could also serve as a prototype for fixes to https://github.com/visionmedia/ejs/issues/35 so hopefully @visionmedia spots this too.

### `block(name,html)`

First, I've implemented a simple `blocks` local function that allows a layout to receive scripts, stylesheets etc from another template.

e.g. if you have this template in `stuff.ejs`:

```html
<% block('sidebar', '
bar
') %>
<% block('sidebar', '
quux
') %>

I'm the main content here!

```

And this layout in `layout-blocks.ejs`:

```html

<%-body%>

<%-block('sidebar')%>

```

Then when you do: `res.render('stuff.ejs', { layout: 'layout-blocks.ejs' })` you get:

```html

I'm the main content here!

bar

quux

```

I didn't want to get into the internals of ejs parsing so I didn't make a nicer way to use bigger blocks yet. I will probably adjust the output to match the syntax of https://github.com/aseemk/express-blocks (ie `blocks.sidebar` instead of `blocks('sidebar')`). That library also has nice helpers for stylesheets and scripts and was definitely an inspiration for this feature.

If I do a nicer way to append blocks it will probably be something like:

```html
<%blocks('sidebar',%>
bar

<%)%>
```

Or maybe:

```html
<%sidebar%>
bar

<%/sidebar%>
```

With `<%-sidebar%>` or `<%-blocks.sidebar%>`to include the results in a layout either way. I'm not sure though - probably worth a survey of rails, django, smarty etc. to see how it's done there?

### `inherits(view)`

This one is a bit simpler. I want to call it `layout` but for the moment that conflicts with the backwards-compatible flag for applying a layout via `res.render(..., { layout: 'foo' })`.

If you have this template in `child.ejs`:

```html
<%inherits('parent')%>

I am from the child!

```

And this layout in `parent.ejs`:

```html
<%-body%>
```

Then `res.render('child')` will produce:

```html

I am from the child!

```

Even if `layout` is set to false in the render options... which I think is right. This is the way Express is going already (see https://github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x) and the Jade template engine implements something similar already. I'm in favor of removing the `layout` flag and default layouts entirely and letting templates declare if they want a layout - what do you think? This will allow trivially renaming the `inherits(...)` function to `layout(...)` without needing to resort to hacking around with the options and locals objects, which are already a bit messy. I already switched layouts off by default, though the backwards compatible side of keeping them on is tempting of course.

### `include(view)`

Right now this is shorthand for `partial(view,options)` where options are the original options passed to the parent template. As I look at your implementation of `partial` now I wonder if that's the right thing. In the end I'd like this to support other view engines too, so you could include a block of markdown or whatever instead of just ejs.

### caching

The current master branch doesn't observe the `options.cache` setting... partly because I don't think it can see that setting while implemented as middleware. I've rearranged things so that the library is instead registered as a `view engine` for `ejs`.

So instead of this:

```javascript
var partials = require('express-partials');
app.use(partials());
```

You now do this:

```javascript
var partials = require('express-partials');
app.engine('ejs', partials);
app.locals({
layout: true
})
```

Another benefit to this is that views that don't use res.render don't pay the price of setting up the locals and applying the patches - not a big concern but it seems tidier.

### tests

Right now to test with caching enabled I run `NODE_ENV=production ./node_modules/mocha/bin/mocha -r should` - all tests are passing, but it would probably be worth writing some more, and possibly worth wiring up the test file to toggle process.env.NODE_ENV and do another pass with a new app instance. If anyone tries this and you find yourself adding more tests, watch out for new lines in your editor - it makes composing the precise expected html output quite tricky!

Hope this all makes sense and look forward to hearing your thoughts!