├── .gitignore ├── package.json ├── LICENSE.txt ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # WebStorm 2 | .idea 3 | 4 | # Node.js 5 | node_modules 6 | npm-debug.log 7 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-ejs-extend", 3 | "version": "0.0.1", 4 | "description": "Layouts support for EJS templates in Express 3+.", 5 | "keywords": [ 6 | "express", 7 | "ejs", 8 | "template", 9 | "layout" 10 | ], 11 | "homepage": "https://github.com/bryanjhv/express-ejs-extend", 12 | "bugs": "https://github.com/bryanjhv/express-ejs-extend/issues", 13 | "license": "MIT", 14 | "author": "Bryan Horna (https://bryanjhv.github.io)", 15 | "main": "index.js", 16 | "repository": "bryanjhv/express-ejs-extend", 17 | "dependencies": { 18 | "ejs": ">=2.4.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Bryan Horna 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var ejs = require('ejs'), 2 | path = require('path'); 3 | 4 | 5 | /** 6 | * Express EJS engine with layout support. 7 | * 8 | * This function is the only export for the module, and it's 9 | * ready to be used as an Express engine. 10 | * It exports to the view a method named `extend`, which in 11 | * opposite to the normal `include` built-in, it captures the 12 | * content in the file which is called and passes to the 13 | * filename specified in it. It just intercepts the first call 14 | * to `extend` so if you try to use more than a layout it will 15 | * use the last one. 16 | * 17 | * @param {string} filename - The filename of rendered view. 18 | * @param {object} options - Passed by Express. 19 | * @param {function(Error, string?)} callback - Once finished. 20 | * @throws {Error} If no filename was given to `extend`. 21 | */ 22 | module.exports = function expressEjsExtend(filename, options, callback) { 23 | var extension = null; 24 | options.extend = function (filename, data) { 25 | if (!filename) throw new Error('Missing filename for EJS extend.'); 26 | 27 | if (!data) data = {}; 28 | extension = {filename: filename, data: data}; 29 | return null; 30 | }; 31 | 32 | // render normally the view 33 | ejs.renderFile(filename, options, function (err, str) { 34 | if (err) return callback(err); 35 | if (!extension) return callback(err, str); 36 | 37 | // if we get here, `extend` was called 38 | var data = extension.data; 39 | // copy `extend` data 40 | for (var key in data) { 41 | options[key] = data[key]; 42 | } 43 | options.content = str; 44 | 45 | // render layout with content 46 | var layout = extension.filename; 47 | if (!path.extname(layout)) layout += '.ejs'; 48 | layout = path.resolve(path.dirname(filename), layout); 49 | ejs.renderFile(layout, options, callback); 50 | }); 51 | }; 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Express EJS Extend     [![Donate][paybtn]][paylnk] 2 | 3 | Layouts support for [EJS][ejs] templates in [Express 3+][express]. 4 | 5 | 6 | ## Usage 7 | 8 | First, add it as engine in your app: 9 | 10 | ```js 11 | // server.js 12 | 13 | var express = require('express'), 14 | path = require('path'); 15 | 16 | 17 | var app = express(); 18 | 19 | app.engine('ejs', require('express-ejs-extend')); // add this line 20 | app.set('view engine', 'ejs'); 21 | app.set('views', path.join(__dirname, 'views')); 22 | 23 | app.get('/', function (req, res) { 24 | res.render('index', {title: 'world!'}); 25 | }); 26 | 27 | app.listen(3000); 28 | ``` 29 | 30 | Finally, in your views, call the `extend` function: 31 | 32 | ```ejs 33 | <%# views/index.ejs %> 34 | 35 | <% extend('layout') %> 36 | 37 |

Hello <%= title %>

38 | ``` 39 | 40 | ```ejs 41 | <%# views/layout.ejs %> 42 | 43 | 44 | 45 | 46 | <%- content %> 47 | 48 | 49 | ``` 50 | 51 | That's all, your `GET /` will render: 52 | 53 | ```html 54 | 55 | 56 | 57 |

Hello world!

58 | 59 | 60 | ``` 61 | 62 | ### Notes: 63 | 64 | * In your view (the one that calls `extend`), you can surround the `extend` with 65 | any combination of (`<%` or `<%-`) and (`%>` or `-%>`). 66 | * In your layout, it's **recommended** to use exactly `<%- content %>` so the 67 | engine doesn't escape your HTML tags. Also you can end it with `-%>` instead 68 | to avoid any trailing `\n`. 69 | * The signature of `extend` is: `extend(layout[, data])`, so you can also pass 70 | an object with data and that will be passed to the layout. 71 | 72 | 73 | ## License 74 | 75 | This project is released under the [MIT license](LICENSE.txt). 76 | 77 | 78 | [ejs]: http://ejs.co 79 | [express]: http://expressjs.com 80 | 81 | [paybtn]: https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif 82 | [paylnk]: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=DVB7SSMVSHGTN 83 | --------------------------------------------------------------------------------