├── .gitignore ├── LICENSE ├── README.md ├── benchmark.png ├── docs ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── 6.jpeg ├── bg.jpg └── index.html ├── es6-renderer.js ├── package-lock.json ├── package.json └── test ├── es6-renderer.spec.js ├── index.html └── partial.html /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Express ES6 string template engine 2 | ====== 3 | 4 | ES6 Renderer is simple, super fast, and extendable Template Engine for Node and Express applications which uses pure ES6 Javascript syntax. 5 | It works by scanning files in a working directory, then reading the contents of the files and converting them from plain strings to ES6 template strings. ES6 template strings are string literals enclosed by the back-tick. They feature String Interpolation, Embedded Expressions, Multiline strings and String Tagging for safe HTML escaping, localisation, etc. Once convertion is completed its then compiled to plain text by the V8 engine, harnessing 100% of its power. Being less than 1kb, ES6 Renderer offloads a lot of the processing directly to the V8 interpreter, which compiles the code and runs as fast as the rest of the Express App. In fact, ES6 Renderer shouldn't add any overhead to the project at all! It should also allow us to implement any functionality we like within the bounds of Javascript. 6 | 7 | Minimum requirements Node.js `v4.0.0`. 8 | 9 | [![Package Version](https://img.shields.io/badge/npm-4.0.0-blue.svg)](https://www.npmjs.com/package/express-es6-template-engine) 10 | 11 | ### Benchmarks 12 | 13 | Testing ES6 Renderer performance was a great opportunity to see how it stacked-up beside others. Our speed test compiled one main template containing an array of string, an object literal and conditional statements. 14 | 15 | ![Benchmarks](benchmark.png) 16 | 17 | ### Playground 18 | 19 | This template engines is essential tools in web development that allows you to generate dynamic HTML content by combining templates with data. Explore ES6 Renderer [Playground demo](https://dondido.github.io/express-es6-template-engine/) to learn how to use it. 20 | 21 | ### Installation 22 | 23 | ```bash 24 | $ npm i express-es6-template-engine --save 25 | ``` 26 | 27 | ### Features 28 | 29 | * No Dependencies 30 | * Fully Configurable 31 | * Compiled and interpreted by V8 (Super Fast) 32 | * Learning new syntax is not required 33 | * Partials Support 34 | * Conditional Support 35 | * Iterators Support 36 | * Native Javascript Support 37 | 38 | ### Usage 39 | 40 | #### Prerequisites 41 | 42 | List of used html files in the `views` folder: 43 | 44 | `index.html` 45 | 46 | ```html 47 | 48 | 49 | 50 |

${title}

51 | 52 | 53 | ``` 54 | 55 | `template.html` 56 | 57 | ```html 58 | 59 | 60 | 61 |

${title}

62 |
${partial}
63 | 64 | 65 | ``` 66 | 67 | `partial.html` 68 | 69 | ```html 70 |

The fastest javascript template string engine!

71 | ``` 72 | 73 | `partial-conditional.html` 74 | 75 | ```html 76 | ES6 Renderer is ${maintainedBy ? `a template engine maintained by ${maintainedBy}` : 'not maintained anymore'}. 77 | ``` 78 | 79 | `partial-iteration.html` 80 | 81 | ```html 82 |
83 | ${features.map(f => ` 84 |
${f.dt}
85 |
${f.dd}
86 | `).join('')} 87 |
88 | ``` 89 | 90 | #### Setup with Express 91 | 92 | The basics required to integrate ES6 renderer in your app are pretty simple and easy to implement: 93 | 94 | ```javascript 95 | const express = require('express'), 96 | es6Renderer = require('express-es6-template-engine'), 97 | app = express(); 98 | 99 | app.engine('html', es6Renderer); 100 | app.set('views', 'views'); 101 | app.set('view engine', 'html'); 102 | 103 | app.get('/', function(req, res) { 104 | res.render('index', {locals: {title: 'Welcome!'}}); 105 | }); 106 | 107 | app.listen(3000); 108 | ``` 109 | 110 | Before Express can render template files, the following application settings must be set: 111 | 112 | - views, the directory where the template files are located. Eg: app.set('views', './views') 113 | - view engine, the template engine to use. Eg: app.set('view engine', 'html') 114 | 115 | HTML template file named `index.html` in the views directory is needed (the content of the file can be found in the prerequisites section). Route to render the html file is expected. If the view engine property is not set, we must specify the extension of the view file. Otherwise, it can be safely omitted. 116 | 117 | ```javascript 118 | app.render('index', {locals: {title: 'ES6 Renderer'}}); 119 | ``` 120 | 121 | Express-compliant template engines such as ES6 Renderer export a function named __express(filePath, options, callback), which is called by the res.render() function to render the template code. When a request is made to the home page, the index.html file will be rendered as HTML. 122 | 123 | #### Setup without Express 124 | 125 | To get up and running without having to worry about managing extra libraries one only needs the following: 126 | 127 | ```javascript 128 | const es6Renderer = require('express-es6-template-engine'); 129 | es6Renderer( 130 | __dirname + '/views/index.html', 131 | { locals: { title: 'ES6 Renderer' } }, 132 | (err, content) => err || content 133 | ); 134 | ``` 135 | 136 | The content below will be rendered on the client side as a response from both setups: 137 | 138 | ```html 139 | 140 | 141 | 142 |

ES6 Renderer

143 | 144 | 145 | ``` 146 | 147 | #### Rendering a template 148 | 149 | Within your app route callback, call `res.render`, passing any partials and local variables required by your template. For example: 150 | 151 | ```javascript 152 | app.get('/', function(req, res) { 153 | res.render('template', { 154 | locals: { 155 | title: 'ES6 Renderer' 156 | }, 157 | partials: { 158 | partial: 'partial' 159 | } 160 | }); 161 | }); 162 | ``` 163 | 164 | Partial with a file name `partial.html` (see the content of the file in the prerequisites section above) will be injected into `template.html`: 165 | 166 | ```html 167 | 168 | 169 | 170 |

ES6 Renderer

171 |

The fastest javascript template string engine!

172 | 173 | 174 | ``` 175 | 176 | All templates files paths are defined as absolute to the root directory of the project. 177 | 178 | #### Compiling a string 179 | 180 | ES6 Renderer rendering functionality has separate scanning, parsing, string generation and response sending phases. Compilation is pretty much the same but without the response sending phase. This feature can be useful for pre-processing templates on the server. 181 | Compiling has the following syntax: 182 | 183 | ```javascript 184 | const titleTpl = '${engineName} - The fastest javascript template string engine!'; 185 | const cb = (err, content) => err || content; 186 | 187 | // sync - second parameter is a string representation of an array of variable names. 188 | // The returned function is called with a string representation of an array of variable values. 189 | const compiled = es6Renderer(titleTpl, 'engineName')('ES6 Renderer'); 190 | // async - second parameter is an object and third parameter is a callback function 191 | es6Renderer(titleTpl,{ template: true, locals:{ engineName: 'ES6 Renderer' } }, cb); 192 | ``` 193 | Both methods will result in the following output: 194 | 195 | ``` 196 | ES6 Renderer - The fastest javascript template string engine! 197 | ``` 198 | The template engine allows both synchronous and asynchronous method invocations. If string is rendered as in the examples provided above a 'template' option needs to be set to true. The preceding synchronous invocation returns an output immediately in response to the function execution. Alternatively, you can specify partials and omit template parameter to force file lookup and content reading and invoke the function asynchronously. 199 | 200 | 201 | #### Compiling a template 202 | 203 | The two functions `app.render` and `es6Renderer` are almost identical, but they require slightly different parameters to be passed. While `app.render` uses an absolute path, or a path relative to the views setting, `es6Renderer` expects a path relative to root folder. 204 | They both return the rendered content of a view via the callback function. The callback function which is provided as a third parameter is called once the asynchronous activity is completed. The output in the two examples provided below is the same: 205 | 206 | ```javascript 207 | app.render('template', { 208 | locals: { 209 | title: 'ES6 Renderer' 210 | }, 211 | partials: { 212 | template: __dirname + '/views/partial' 213 | } 214 | }, (err, content) => err || content); 215 | ``` 216 | ```javascript 217 | es6Renderer(__dirname + '/views/template.html', { 218 | locals: { 219 | title: 'ES6 Renderer' 220 | }, 221 | partials: { 222 | template: __dirname + '/views/partial.html' 223 | } 224 | }, (err, content) => err || content); 225 | ``` 226 | On average `es6Renderer` yields slightly better performance than `app.render`. Async function invocation of `es6Renderer` also returns a promise, which enables us to chain method calls: 227 | ```javascript 228 | const compile = es6Renderer(__dirname + '/views/template.html', { 229 | locals: { 230 | title: 'ES6 Renderer' 231 | }, 232 | partials: { 233 | template: __dirname + '/views/partial.html' 234 | } 235 | }, (err, content) => err || content); 236 | compile.then(output => res.send(output)) 237 | ``` 238 | 239 | #### Compiling a nested template 240 | 241 | Template nesting is currently not supported by the engine. A simple workaround to this issue would be to perform multiple template compilations: 242 | 243 | ```javascript 244 | const renderPage = (err, content) => res.render('template', { 245 | locals: { 246 | partial: content 247 | } 248 | }); 249 | es6Renderer(__dirname + '/views/partial-conditional.html', { 250 | locals: { 251 | maintainedBy: 'Good Samaritans' 252 | } 253 | }, renderPage); 254 | ``` 255 | #### Precompiling 256 | 257 | ES6 Renderer allows us bypassing Express view rendering for speed and modularity. Compiling a template is much slower than rendering it, so when it comes to speed, we should precompile our templates as part of the optimisation process. The result of precompilation can be stored to an object: 258 | ```javascript 259 | const text = '${engineName} - The fastest javascript template string engine in the whole ${place}!'; 260 | const precompiled = es6Renderer(text, 'engineName, place'); 261 | ``` 262 | and then invoked whenever needed: 263 | ```javascript 264 | console.log(precompiled('ES6 Renderer', 'multiverse')); 265 | ``` 266 | To make use of this precompilation, templates should be compiled with names that the compiler would expect and the result function called with an argument list that consists of values relative to the names. If no property name is defined a default one is created with a value of '$': 267 | ```javascript 268 | const text = '${$.engineName} - The fastest javascript template string engine in the whole ${$.place}!'; 269 | console.log(es6Renderer(text)({ engineName: 'ES6 Renderer', place: 'multiverse' }); 270 | ``` 271 | This allows us to create an application that is more flexible, independent from a framework, easier to understand and better performing. 272 | 273 | 274 | 275 | #### Conditional statements 276 | 277 | ES6 Renderer dynamically evaluates code in JavaScript. If the argument is an expression, ES6 Renderer evaluates the expression. If the argument is one or more JavaScript statements, the engine executes the statements. A simplified example of using conditional statement is presented below. 278 | 279 | A route path on the server side: 280 | 281 | ```javascript 282 | res.render('partial-conditional', { 283 | locals: { 284 | maintainedBy: 'Good Samaritans' 285 | } 286 | }); 287 | ``` 288 | 289 | Will result in the following: 290 | 291 | ```html 292 | ES6 Renderer is a template engine maintained by Good Samaritans. 293 | ``` 294 | 295 | #### Iterators 296 | 297 | Iterating over arrays and objects is quite straight forward and intuitive (knowledge of basic javascript here is essential). An object literal is passed to a html template: 298 | 299 | ```javascript 300 | res.render('partial-iteration', { 301 | locals: { 302 | features: [ 303 | { 304 | dt: 'Multi-line strings', 305 | dd: 'Any new line characters inserted in the source are part of the template string.' 306 | }, 307 | { 308 | dt: 'Expression interpolation', 309 | dd: 'Template strings can contain placeholders. These are indicated by dollar sign and curly braces.' 310 | }, 311 | ] 312 | } 313 | }); 314 | ``` 315 | 316 | The following is received by the client side: 317 | 318 | ```html 319 |
320 |
Multi-line strings
321 |
Any new line characters inserted in the source are part of the template string.
322 |
Expression interpolation
323 |
Template strings can contain placeholders. These are indicated by dollar sign and curly braces.
324 |
325 | ``` 326 | 327 | #### Error Handling 328 | 329 | ES6 Renderer catches and processes errors that occur both synchronously and asynchronously. ES6 Renderer comes with a default error handler so you don’t need to write your own to get started. 330 | Errors that occur in synchronous code require no extra work. If synchronous code throws an error, then ES6 Renderer will catch and process it. For example. 331 | 332 | ```javascript 333 | const text = '${engineName} - The fastest javascript template string engine in the whole ${place}!'; 334 | const err = es6Renderer(text, 'engineName')('ES6 Renderer', 'multiverse'); 335 | expect(err instanceof Error).to.equal(true); 336 | ``` 337 | 338 | For errors returned from asynchronous functions, you must pass them to the callback function, where ES6 Renderer will catch and process them. A viable alternative will be to use native promise catch or reject methods. The example underneath handles both cases simultaneously: 339 | 340 | ```javascript 341 | es6Renderer( 342 | __dirname + "/index.html", 343 | { locals: { engineName: "ES6 Renderer", footer: "MIT License" } }, 344 | (err) => expect(err instanceof Error).to.equal(true); 345 | ).then((err) => expect(err instanceof Error).to.equal(true)); 346 | ``` 347 | 348 | ### License 349 | 350 | MIT License 351 | 352 | Copyright (c) 2015 Dian Dimitrov 353 | 354 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 355 | 356 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 357 | 358 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 359 | -------------------------------------------------------------------------------- /benchmark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondido/express-es6-template-engine/dd0ac4c9ea560fd02392797dc04ce4ca6b791691/benchmark.png -------------------------------------------------------------------------------- /docs/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondido/express-es6-template-engine/dd0ac4c9ea560fd02392797dc04ce4ca6b791691/docs/1.jpg -------------------------------------------------------------------------------- /docs/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondido/express-es6-template-engine/dd0ac4c9ea560fd02392797dc04ce4ca6b791691/docs/2.jpg -------------------------------------------------------------------------------- /docs/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondido/express-es6-template-engine/dd0ac4c9ea560fd02392797dc04ce4ca6b791691/docs/3.jpg -------------------------------------------------------------------------------- /docs/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondido/express-es6-template-engine/dd0ac4c9ea560fd02392797dc04ce4ca6b791691/docs/4.jpg -------------------------------------------------------------------------------- /docs/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondido/express-es6-template-engine/dd0ac4c9ea560fd02392797dc04ce4ca6b791691/docs/5.jpg -------------------------------------------------------------------------------- /docs/6.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondido/express-es6-template-engine/dd0ac4c9ea560fd02392797dc04ce4ca6b791691/docs/6.jpeg -------------------------------------------------------------------------------- /docs/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dondido/express-es6-template-engine/dd0ac4c9ea560fd02392797dc04ce4ca6b791691/docs/bg.jpg -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 253 | Express ES6 temlpate engine - the fastest and unopinionated javascript template engine for Node and Express 254 | 255 | 256 | Fork me on GitHub 257 | 258 |
259 |
Est. 2015
260 |

ES6RENDERER

261 |
Express Template Engine
262 |
263 | 264 |

Origins

265 |

The art of creating code that is "environment agnostic" recognised as "Isomorphic JavaScript", allows us to render the views of the application from the server (during the initialisation of the app) and then keep rendering the other views directly in the browser (avoiding a full page refresh) while the user keep navigating across the different sections. One of the advantages of having ES6 renderer as template engine for the backend of a web application is that one have to deal only with javascript template literals as a single syntax across the web stack. With this in mind the engine can be seen as the perfect tool that facilitates logic sharing between the frontend and the backend in order to reduce the codebase duplication between the browser and the server to the bare minimun. Express ES6 temlpate engine is a minimal and flexible Node web application library, providing a robust set of features for building single and multi page, and hybrid web applications. As a framework-independent technology, ES6 Renderer is an engine one can adopt and hit the ground running with immediately. 266 |

267 | 268 |

Features

269 |
270 |
271 |
272 |
273 |
274 |
275 |

NO DEPENDENCIES

276 |

A simple and lightweight vanilla library.

277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |

ZERO LEARNING

287 |

Grasping new syntax is not required.

288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
296 |
297 |

LOGIC STATEMENTS

298 |

Conditional operators and ternary expressions.

299 |
300 |
301 |
302 |
303 |
304 |
305 |
306 |
307 |
308 |

LOOPS (ITERATIONS)

309 |

Native ways to iterate over arrays and objects.

310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |

PARTIALS SUPPORT

320 |

Layout and partials support.

321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |

TEMPLATE PRECOMPILATION

331 |

Precompiling and template caching.

332 |
333 |
334 |
335 |
336 |
337 |

338 |

Online compiler

339 |

Every developer has been in a situation where they simply want to try and evaluate a framework or library, without having to install it or include it in a project. The online compiler provides a custom environment to test and fiddle with Express ES6 template engine functionality right inside a browser and see the results as they type in real time. A quick tour of the engine logic implementation will give you a better understanding of what it provides and why you should use it.

The general rendering process of the engine is rather simple. es6Renderer('template', {locals}) compiles the provided source code into a javaScript function. Calling that resultant function with an object as an argument returns a string of HTML rendered with our data. This methods combine compiling and rendering into one step. The 'template' string used as a first argument is a reference to a 'template.html' file in a view directory with a content presented in the first text area below (see Template). The data object called 'locals' provided in the second text area (see Data) has properties that are local variables within the content.

340 |

Template

341 | 342 |

Data

343 | 352 |

Result

353 |
354 |

355 | 356 |

Benchmarks

357 |

It’s not uncommon that from time to time I am asked about what template engine do I use and why. After my reply, I get something like: “isn’t that one slow?”. Usually, when developers talk in regards to performance, I always utter something like: “well, that depends on …”, and there one can insert his slow performance reasoning of choice, if it can be bad or not that bad.

358 |

Benchmark testing was done with Marko's brilliant Templating benchmark suite. Testing ES6 Renderer performance was a great opportunity to see how it stacked-up beside others. Our speed test compiled one main template containing an array of string, an object literal and conditional statements.

359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 |
RUNTIME PERFORMANCE
✓ es6Renderer300,987 op/s(fastest)
✗ pug155,015 op/s(48.50% slower)
✗ marko143,375 op/s(52.37% slower)
✗ dot129,364 op/s(57.02% slower)
✗ handlebars46,871 op/s(84.43% slower)
✗ swig43,996 op/s(85.38% slower)
✗ dust39,834 op/s(86.77% slower)
✗ jade21,373 op/s(92.90% slower)
✗ nunjucks18,313 op/s(93.92% slower)
✗ vue5,251 op/s(98.26% slower)
✗ react2,218 op/s(99.26% slower)
377 |

As we see from the chart above ES6 Renderer is the fastest of the all engines compared. It was almost twice as fast as the second place runner on the list. The data presented above is not intended to trash about any of the view engines. The procedure to make the comparison on performance is quite simple and not scientific at all. From a technical point of view it's up to the developer to choose the templating engine that makes him more productive. It is also important to bear in mind that for frontend designers accustomed to code in HTML only, the learning curve for them will be of relevance.

378 | 379 |

Source

380 | github.com/dondido/express-es6-template-engine 381 |

by Dian Dimitrov, MIT license

382 | 383 |

NPM

384 | https://www.npmjs.com/package/express-es6-template-engine 385 | 386 |

Author

387 | @dondido 388 | 389 | 427 | 428 | 429 | -------------------------------------------------------------------------------- /es6-renderer.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); // this engine requires the fs module 2 | /* jshint ignore:start */ 3 | const compile = (content, $ = '$') => Function($, 'return `' + content + '`;'); 4 | const precompile = (content, $ = '$') => 5 | Function($, 'try { return `' + content + '`;} catch(err) { return err }'); 6 | /* jshint ignore:end */ 7 | const setPath = (views, ref, ext) => ref.endsWith(ext) ? ref : views + '/' + ref + ext; 8 | const getPartial = (path, cb = 'resolveNeutral') => { 9 | const findFile = function(resolve, reject) { 10 | this.resolveNeutral = (err, content) => err ? reject(err) : resolve(content); 11 | this.resolvePositive = (err, content) => resolve(err || content); 12 | fs.readFile(path, 'utf-8', this[cb]); 13 | }; 14 | return new Promise(findFile); 15 | }; 16 | 17 | module.exports = (path, options, render) => { 18 | if(options === undefined || typeof options === 'string') { 19 | return precompile(path, options); 20 | } 21 | let willResolve; 22 | let willReject; 23 | const fulfillPromise = (resolve, reject) => { 24 | willResolve = resolve; 25 | willReject = reject; 26 | }; 27 | const handleRejection = (err) => { 28 | const output = render(err); 29 | return willReject ? willReject(err) : output; 30 | }; 31 | const {locals = {}, partials = {}, settings, template} = options; 32 | const assign = (err, content) => { 33 | const send = () => { 34 | if(render) { 35 | try { 36 | const compiled = compile(content, localsKeys)(...localsValues); 37 | const output = render(null, compiled); 38 | return willResolve ? willResolve(compiled) : output; 39 | } catch(err) { 40 | return handleRejection(err); 41 | } 42 | } 43 | try { 44 | return willResolve(compile(content, localsKeys)(...localsValues)); 45 | } catch (err) { 46 | return willReject(err); 47 | } 48 | } 49 | if(err) { 50 | return handleRejection(err); 51 | } 52 | const localsKeys = Object.keys(locals); 53 | const localsValues = localsKeys.map(i => locals[i]); 54 | const partialsKeys = Object.keys(partials); 55 | const compilePartials = values => { 56 | const valTempList = localsValues.concat(values); 57 | try { 58 | localsValues.push(...values.map(i => compile(i, localsKeys)(...valTempList))); 59 | } catch (err) { 60 | return render(err); 61 | } 62 | send(); 63 | }; 64 | if(partialsKeys.length) { 65 | const applySettings = () => { 66 | const ext = '.' + settings['view engine']; 67 | if(typeof settings.views === 'string') { 68 | return i => getPartial(setPath(settings.views, partials[i], ext)); 69 | } 70 | return i => { 71 | const getFile = view => getPartial(setPath(view, partials[i], ext), 'resolvePositive'); 72 | const getFirst = value => typeof value === 'string'; 73 | const searchFile = (resolve, reject) => { 74 | const getContent = values => resolve(values.find(getFirst)); 75 | Promise.all(settings.views.map(getFile)).then(getContent); 76 | }; 77 | return new Promise(searchFile); 78 | }; 79 | }; 80 | const setPartial = settings ? applySettings() : i => getPartial(partials[i]); 81 | localsKeys.push(...partialsKeys); 82 | const willGetPartials = Promise.all(partialsKeys.map(setPartial)) 83 | .then(compilePartials, handleRejection); 84 | return willResolve ? willGetPartials : new Promise(fulfillPromise); 85 | } 86 | return send(); 87 | }; 88 | if(template) { 89 | render = render || ((err, content) => err || content); 90 | return assign(null, path); 91 | } 92 | fs.readFile(path, 'utf-8', assign); 93 | return new Promise(fulfillPromise); 94 | }; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-es6-template-engine", 3 | "version": "2.2.3", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 10 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 11 | "dev": true, 12 | "requires": { 13 | "mime-types": "~2.1.24", 14 | "negotiator": "0.6.2" 15 | } 16 | }, 17 | "array-flatten": { 18 | "version": "1.1.1", 19 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 20 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", 21 | "dev": true 22 | }, 23 | "assertion-error": { 24 | "version": "1.1.0", 25 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 26 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 27 | "dev": true 28 | }, 29 | "balanced-match": { 30 | "version": "1.0.0", 31 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 32 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 33 | "dev": true 34 | }, 35 | "body-parser": { 36 | "version": "1.19.0", 37 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 38 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 39 | "dev": true, 40 | "requires": { 41 | "bytes": "3.1.0", 42 | "content-type": "~1.0.4", 43 | "debug": "2.6.9", 44 | "depd": "~1.1.2", 45 | "http-errors": "1.7.2", 46 | "iconv-lite": "0.4.24", 47 | "on-finished": "~2.3.0", 48 | "qs": "6.7.0", 49 | "raw-body": "2.4.0", 50 | "type-is": "~1.6.17" 51 | }, 52 | "dependencies": { 53 | "debug": { 54 | "version": "2.6.9", 55 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 56 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 57 | "dev": true, 58 | "requires": { 59 | "ms": "2.0.0" 60 | } 61 | } 62 | } 63 | }, 64 | "brace-expansion": { 65 | "version": "1.1.11", 66 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 67 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 68 | "dev": true, 69 | "requires": { 70 | "balanced-match": "^1.0.0", 71 | "concat-map": "0.0.1" 72 | } 73 | }, 74 | "browser-stdout": { 75 | "version": "1.3.1", 76 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", 77 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", 78 | "dev": true 79 | }, 80 | "bytes": { 81 | "version": "3.1.0", 82 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 83 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", 84 | "dev": true 85 | }, 86 | "chai": { 87 | "version": "4.2.0", 88 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", 89 | "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", 90 | "dev": true, 91 | "requires": { 92 | "assertion-error": "^1.1.0", 93 | "check-error": "^1.0.2", 94 | "deep-eql": "^3.0.1", 95 | "get-func-name": "^2.0.0", 96 | "pathval": "^1.1.0", 97 | "type-detect": "^4.0.5" 98 | } 99 | }, 100 | "check-error": { 101 | "version": "1.0.2", 102 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 103 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 104 | "dev": true 105 | }, 106 | "commander": { 107 | "version": "2.15.1", 108 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", 109 | "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", 110 | "dev": true 111 | }, 112 | "concat-map": { 113 | "version": "0.0.1", 114 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 115 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 116 | "dev": true 117 | }, 118 | "content-disposition": { 119 | "version": "0.5.3", 120 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 121 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 122 | "dev": true, 123 | "requires": { 124 | "safe-buffer": "5.1.2" 125 | } 126 | }, 127 | "content-type": { 128 | "version": "1.0.4", 129 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 130 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 131 | "dev": true 132 | }, 133 | "cookie": { 134 | "version": "0.4.0", 135 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 136 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", 137 | "dev": true 138 | }, 139 | "cookie-signature": { 140 | "version": "1.0.6", 141 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 142 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", 143 | "dev": true 144 | }, 145 | "debug": { 146 | "version": "3.1.0", 147 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 148 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 149 | "dev": true, 150 | "requires": { 151 | "ms": "2.0.0" 152 | } 153 | }, 154 | "deep-eql": { 155 | "version": "3.0.1", 156 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", 157 | "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", 158 | "dev": true, 159 | "requires": { 160 | "type-detect": "^4.0.0" 161 | } 162 | }, 163 | "depd": { 164 | "version": "1.1.2", 165 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 166 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", 167 | "dev": true 168 | }, 169 | "destroy": { 170 | "version": "1.0.4", 171 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 172 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", 173 | "dev": true 174 | }, 175 | "diff": { 176 | "version": "3.5.0", 177 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", 178 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", 179 | "dev": true 180 | }, 181 | "ee-first": { 182 | "version": "1.1.1", 183 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 184 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", 185 | "dev": true 186 | }, 187 | "encodeurl": { 188 | "version": "1.0.2", 189 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 190 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 191 | "dev": true 192 | }, 193 | "escape-html": { 194 | "version": "1.0.3", 195 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 196 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", 197 | "dev": true 198 | }, 199 | "escape-string-regexp": { 200 | "version": "1.0.5", 201 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 202 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 203 | "dev": true 204 | }, 205 | "etag": { 206 | "version": "1.8.1", 207 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 208 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", 209 | "dev": true 210 | }, 211 | "express": { 212 | "version": "4.17.1", 213 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 214 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 215 | "dev": true, 216 | "requires": { 217 | "accepts": "~1.3.7", 218 | "array-flatten": "1.1.1", 219 | "body-parser": "1.19.0", 220 | "content-disposition": "0.5.3", 221 | "content-type": "~1.0.4", 222 | "cookie": "0.4.0", 223 | "cookie-signature": "1.0.6", 224 | "debug": "2.6.9", 225 | "depd": "~1.1.2", 226 | "encodeurl": "~1.0.2", 227 | "escape-html": "~1.0.3", 228 | "etag": "~1.8.1", 229 | "finalhandler": "~1.1.2", 230 | "fresh": "0.5.2", 231 | "merge-descriptors": "1.0.1", 232 | "methods": "~1.1.2", 233 | "on-finished": "~2.3.0", 234 | "parseurl": "~1.3.3", 235 | "path-to-regexp": "0.1.7", 236 | "proxy-addr": "~2.0.5", 237 | "qs": "6.7.0", 238 | "range-parser": "~1.2.1", 239 | "safe-buffer": "5.1.2", 240 | "send": "0.17.1", 241 | "serve-static": "1.14.1", 242 | "setprototypeof": "1.1.1", 243 | "statuses": "~1.5.0", 244 | "type-is": "~1.6.18", 245 | "utils-merge": "1.0.1", 246 | "vary": "~1.1.2" 247 | }, 248 | "dependencies": { 249 | "debug": { 250 | "version": "2.6.9", 251 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 252 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 253 | "dev": true, 254 | "requires": { 255 | "ms": "2.0.0" 256 | } 257 | } 258 | } 259 | }, 260 | "finalhandler": { 261 | "version": "1.1.2", 262 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 263 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 264 | "dev": true, 265 | "requires": { 266 | "debug": "2.6.9", 267 | "encodeurl": "~1.0.2", 268 | "escape-html": "~1.0.3", 269 | "on-finished": "~2.3.0", 270 | "parseurl": "~1.3.3", 271 | "statuses": "~1.5.0", 272 | "unpipe": "~1.0.0" 273 | }, 274 | "dependencies": { 275 | "debug": { 276 | "version": "2.6.9", 277 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 278 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 279 | "dev": true, 280 | "requires": { 281 | "ms": "2.0.0" 282 | } 283 | } 284 | } 285 | }, 286 | "forwarded": { 287 | "version": "0.1.2", 288 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 289 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=", 290 | "dev": true 291 | }, 292 | "fresh": { 293 | "version": "0.5.2", 294 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 295 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", 296 | "dev": true 297 | }, 298 | "fs.realpath": { 299 | "version": "1.0.0", 300 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 301 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 302 | "dev": true 303 | }, 304 | "get-func-name": { 305 | "version": "2.0.0", 306 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 307 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 308 | "dev": true 309 | }, 310 | "glob": { 311 | "version": "7.1.2", 312 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 313 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 314 | "dev": true, 315 | "requires": { 316 | "fs.realpath": "^1.0.0", 317 | "inflight": "^1.0.4", 318 | "inherits": "2", 319 | "minimatch": "^3.0.4", 320 | "once": "^1.3.0", 321 | "path-is-absolute": "^1.0.0" 322 | } 323 | }, 324 | "growl": { 325 | "version": "1.10.5", 326 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", 327 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", 328 | "dev": true 329 | }, 330 | "has-flag": { 331 | "version": "3.0.0", 332 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 333 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 334 | "dev": true 335 | }, 336 | "he": { 337 | "version": "1.1.1", 338 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", 339 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", 340 | "dev": true 341 | }, 342 | "http-errors": { 343 | "version": "1.7.2", 344 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 345 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 346 | "dev": true, 347 | "requires": { 348 | "depd": "~1.1.2", 349 | "inherits": "2.0.3", 350 | "setprototypeof": "1.1.1", 351 | "statuses": ">= 1.5.0 < 2", 352 | "toidentifier": "1.0.0" 353 | } 354 | }, 355 | "iconv-lite": { 356 | "version": "0.4.24", 357 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 358 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 359 | "dev": true, 360 | "requires": { 361 | "safer-buffer": ">= 2.1.2 < 3" 362 | } 363 | }, 364 | "inflight": { 365 | "version": "1.0.6", 366 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 367 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 368 | "dev": true, 369 | "requires": { 370 | "once": "^1.3.0", 371 | "wrappy": "1" 372 | } 373 | }, 374 | "inherits": { 375 | "version": "2.0.3", 376 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 377 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 378 | "dev": true 379 | }, 380 | "ipaddr.js": { 381 | "version": "1.9.1", 382 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 383 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 384 | "dev": true 385 | }, 386 | "media-typer": { 387 | "version": "0.3.0", 388 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 389 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 390 | "dev": true 391 | }, 392 | "merge-descriptors": { 393 | "version": "1.0.1", 394 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 395 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", 396 | "dev": true 397 | }, 398 | "methods": { 399 | "version": "1.1.2", 400 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 401 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 402 | "dev": true 403 | }, 404 | "mime": { 405 | "version": "1.6.0", 406 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 407 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 408 | "dev": true 409 | }, 410 | "mime-db": { 411 | "version": "1.43.0", 412 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", 413 | "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", 414 | "dev": true 415 | }, 416 | "mime-types": { 417 | "version": "2.1.26", 418 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", 419 | "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", 420 | "dev": true, 421 | "requires": { 422 | "mime-db": "1.43.0" 423 | } 424 | }, 425 | "minimatch": { 426 | "version": "3.0.4", 427 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 428 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 429 | "dev": true, 430 | "requires": { 431 | "brace-expansion": "^1.1.7" 432 | } 433 | }, 434 | "minimist": { 435 | "version": "1.2.6", 436 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", 437 | "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", 438 | "dev": true 439 | }, 440 | "mkdirp": { 441 | "version": "0.5.1", 442 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 443 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 444 | "dev": true 445 | }, 446 | "mocha": { 447 | "version": "5.2.0", 448 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", 449 | "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", 450 | "dev": true, 451 | "requires": { 452 | "browser-stdout": "1.3.1", 453 | "commander": "2.15.1", 454 | "debug": "3.1.0", 455 | "diff": "3.5.0", 456 | "escape-string-regexp": "1.0.5", 457 | "glob": "7.1.2", 458 | "growl": "1.10.5", 459 | "he": "1.1.1", 460 | "minimatch": "3.0.4", 461 | "mkdirp": "0.5.1", 462 | "supports-color": "5.4.0" 463 | } 464 | }, 465 | "ms": { 466 | "version": "2.0.0", 467 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 468 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 469 | "dev": true 470 | }, 471 | "negotiator": { 472 | "version": "0.6.2", 473 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 474 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", 475 | "dev": true 476 | }, 477 | "on-finished": { 478 | "version": "2.3.0", 479 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 480 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 481 | "dev": true, 482 | "requires": { 483 | "ee-first": "1.1.1" 484 | } 485 | }, 486 | "once": { 487 | "version": "1.4.0", 488 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 489 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 490 | "dev": true, 491 | "requires": { 492 | "wrappy": "1" 493 | } 494 | }, 495 | "parseurl": { 496 | "version": "1.3.3", 497 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 498 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 499 | "dev": true 500 | }, 501 | "path-is-absolute": { 502 | "version": "1.0.1", 503 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 504 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 505 | "dev": true 506 | }, 507 | "path-to-regexp": { 508 | "version": "0.1.7", 509 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 510 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", 511 | "dev": true 512 | }, 513 | "pathval": { 514 | "version": "1.1.1", 515 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", 516 | "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", 517 | "dev": true 518 | }, 519 | "proxy-addr": { 520 | "version": "2.0.6", 521 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 522 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 523 | "dev": true, 524 | "requires": { 525 | "forwarded": "~0.1.2", 526 | "ipaddr.js": "1.9.1" 527 | } 528 | }, 529 | "qs": { 530 | "version": "6.7.0", 531 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 532 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", 533 | "dev": true 534 | }, 535 | "range-parser": { 536 | "version": "1.2.1", 537 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 538 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 539 | "dev": true 540 | }, 541 | "raw-body": { 542 | "version": "2.4.0", 543 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 544 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 545 | "dev": true, 546 | "requires": { 547 | "bytes": "3.1.0", 548 | "http-errors": "1.7.2", 549 | "iconv-lite": "0.4.24", 550 | "unpipe": "1.0.0" 551 | } 552 | }, 553 | "safe-buffer": { 554 | "version": "5.1.2", 555 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 556 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 557 | "dev": true 558 | }, 559 | "safer-buffer": { 560 | "version": "2.1.2", 561 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 562 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", 563 | "dev": true 564 | }, 565 | "send": { 566 | "version": "0.17.1", 567 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 568 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 569 | "dev": true, 570 | "requires": { 571 | "debug": "2.6.9", 572 | "depd": "~1.1.2", 573 | "destroy": "~1.0.4", 574 | "encodeurl": "~1.0.2", 575 | "escape-html": "~1.0.3", 576 | "etag": "~1.8.1", 577 | "fresh": "0.5.2", 578 | "http-errors": "~1.7.2", 579 | "mime": "1.6.0", 580 | "ms": "2.1.1", 581 | "on-finished": "~2.3.0", 582 | "range-parser": "~1.2.1", 583 | "statuses": "~1.5.0" 584 | }, 585 | "dependencies": { 586 | "debug": { 587 | "version": "2.6.9", 588 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 589 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 590 | "dev": true, 591 | "requires": { 592 | "ms": "2.0.0" 593 | }, 594 | "dependencies": { 595 | "ms": { 596 | "version": "2.0.0", 597 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 598 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 599 | "dev": true 600 | } 601 | } 602 | }, 603 | "ms": { 604 | "version": "2.1.1", 605 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 606 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", 607 | "dev": true 608 | } 609 | } 610 | }, 611 | "serve-static": { 612 | "version": "1.14.1", 613 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 614 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 615 | "dev": true, 616 | "requires": { 617 | "encodeurl": "~1.0.2", 618 | "escape-html": "~1.0.3", 619 | "parseurl": "~1.3.3", 620 | "send": "0.17.1" 621 | } 622 | }, 623 | "setprototypeof": { 624 | "version": "1.1.1", 625 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 626 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", 627 | "dev": true 628 | }, 629 | "statuses": { 630 | "version": "1.5.0", 631 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 632 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 633 | "dev": true 634 | }, 635 | "supports-color": { 636 | "version": "5.4.0", 637 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", 638 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", 639 | "dev": true, 640 | "requires": { 641 | "has-flag": "^3.0.0" 642 | } 643 | }, 644 | "toidentifier": { 645 | "version": "1.0.0", 646 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 647 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", 648 | "dev": true 649 | }, 650 | "type-detect": { 651 | "version": "4.0.8", 652 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 653 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 654 | "dev": true 655 | }, 656 | "type-is": { 657 | "version": "1.6.18", 658 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 659 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 660 | "dev": true, 661 | "requires": { 662 | "media-typer": "0.3.0", 663 | "mime-types": "~2.1.24" 664 | } 665 | }, 666 | "unpipe": { 667 | "version": "1.0.0", 668 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 669 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 670 | "dev": true 671 | }, 672 | "utils-merge": { 673 | "version": "1.0.1", 674 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 675 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 676 | "dev": true 677 | }, 678 | "vary": { 679 | "version": "1.1.2", 680 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 681 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 682 | "dev": true 683 | }, 684 | "wrappy": { 685 | "version": "1.0.2", 686 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 687 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 688 | "dev": true 689 | } 690 | } 691 | } 692 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express-es6-template-engine", 3 | "version": "2.2.3", 4 | "description": "Express ES6 string template engine", 5 | "main": "es6-renderer.js", 6 | "scripts": { 7 | "test": "mocha" 8 | }, 9 | "keywords": [ 10 | "ES6", 11 | "express", 12 | "template engine", 13 | "javascript", 14 | "backlash template strings" 15 | ], 16 | "homepage": "https://dondido.github.io/express-es6-template-engine/", 17 | "engine": "node >= 4.0.1", 18 | "repository": { 19 | "type": "git", 20 | "url": "git+https://github.com/dondido/express-es6-template-engine.git" 21 | }, 22 | "author": "Dian Dimitrov", 23 | "license": "MIT", 24 | "devDependencies": { 25 | "minimist": ">=0.2.1", 26 | "chai": "^4.2.0", 27 | "express": "^4.17.1", 28 | "mocha": "^5.2.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/es6-renderer.spec.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | const expect = require("chai").expect; 3 | const express = require("express"); 4 | const es6Renderer = require("../es6-renderer"); 5 | 6 | describe("ES6 Renderer", () => { 7 | 8 | it("is a function", () => { 9 | expect(es6Renderer).to.be.a("function"); 10 | }); 11 | 12 | it("interpolates a provided string", () => { 13 | const titleTpl = "${engineName} - The fastest javascript template string engine!"; 14 | const content = es6Renderer(titleTpl, { 15 | template: true, 16 | locals: { engineName: "ES6 Renderer" } 17 | }); 18 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!"); 19 | }); 20 | 21 | it("throws an error in case of interpolation failure", () => { 22 | const titleTpl = "${engineName} - The fastest javascript template string engine!"; 23 | const err = es6Renderer(titleTpl, { 24 | template: true, 25 | locals: {} 26 | }); 27 | expect(err instanceof Error).to.equal(true); 28 | }); 29 | 30 | describe("External templates", () => { 31 | it("renders a template file with a callback", done => { 32 | es6Renderer( 33 | __dirname + "/index.html", 34 | { locals: { engineName: "ES6 Renderer", footer: "MIT License" } }, 35 | (err, content) => { 36 | expect(err).to.be.null; 37 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!\nMIT License"); 38 | done(); 39 | } 40 | ); 41 | }); 42 | 43 | it("throws an error in case of template interpolation failure with a callback", done => { 44 | es6Renderer( 45 | __dirname + "/index.html", 46 | { locals: { footer: "MIT License" } }, 47 | (err) => { 48 | expect(err instanceof Error).to.equal(true); 49 | done(); 50 | } 51 | ); 52 | }); 53 | 54 | it("renders a template file with a promise", done => { 55 | const assert = (content) => { 56 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!\nMIT License"); 57 | done(); 58 | }; 59 | const willRender = es6Renderer( 60 | __dirname + "/index.html", 61 | { locals: { engineName: "ES6 Renderer", footer: "MIT License" } } 62 | ); 63 | willRender.then(assert); 64 | }); 65 | 66 | it("renders a template file with both promise and callback", done => { 67 | const assert = (content) => { 68 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!\nMIT License"); 69 | done(); 70 | }; 71 | es6Renderer( 72 | __dirname + "/index.html", 73 | { locals: { engineName: "ES6 Renderer", footer: "MIT License" } }, 74 | (err, content) => { 75 | expect(err).to.be.null; 76 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!\nMIT License"); 77 | } 78 | ).then(assert); 79 | }); 80 | 81 | it("throws an error in case of template interpolation with promise failure", done => { 82 | const assert = (err) => { 83 | expect(err instanceof Error).to.equal(true); 84 | done(); 85 | }; 86 | const willRender = es6Renderer( 87 | __dirname + "/index.html", 88 | { locals: {} } 89 | ); 90 | willRender.catch(assert); 91 | }); 92 | 93 | it("throws an error in case of template interpolation with both promise and callback", done => { 94 | const assert = err => expect(err instanceof Error).to.equal(true); 95 | es6Renderer( 96 | __dirname + "/index.html", 97 | { locals: { engineName: "ES6 Renderer", footer: "MIT License" } }, 98 | (err) => { 99 | expect(err instanceof Error).to.equal(true); 100 | done(); 101 | } 102 | ).catch(assert); 103 | }); 104 | 105 | it("merges a string and a partial file with both promise and callback", done => { 106 | const assertPromise = (content) => { 107 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!MIT License"); 108 | done(); 109 | }; 110 | const assertCallback = (err, content) => { 111 | expect(err).to.be.null; 112 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!MIT License"); 113 | }; 114 | const template = "${engineName} - The fastest javascript template string engine!${footer}"; 115 | const willRender = es6Renderer( 116 | template, 117 | { 118 | template: true, 119 | locals: { engineName: "ES6 Renderer", footer: "MIT License" }, 120 | partials: { footer: __dirname + "/partial.html" } 121 | }, 122 | assertCallback 123 | ); 124 | willRender.then(assertPromise); 125 | }); 126 | 127 | it("render partials", done => { 128 | es6Renderer( 129 | __dirname + "/index.html", 130 | { 131 | locals: { engineName: "ES6 Renderer" }, 132 | partials: { 133 | footer: __dirname + "/partial.html" 134 | } 135 | }, 136 | (err, content) => { 137 | expect(err).to.be.null; 138 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!\nMIT License"); 139 | done(); 140 | } 141 | ); 142 | }); 143 | 144 | it("throws an error when template is not found", done => { 145 | const assert = (err) => { 146 | expect(err instanceof Error).to.equal(true); 147 | done(); 148 | }; 149 | es6Renderer( 150 | __dirname + "/inde.html", 151 | { 152 | locals: { engineName: "ES6 Renderer" }, 153 | partials: { 154 | footer: __dirname + "/partial.html" 155 | } 156 | }, 157 | err => expect(err instanceof Error).to.equal(true) 158 | ).catch(assert); 159 | }); 160 | 161 | it("throws an error when partials is not found", done => { 162 | const assert = function(err){ 163 | expect(err instanceof Error).to.equal(true); 164 | done(); 165 | }; 166 | es6Renderer( 167 | __dirname + "/index.html", 168 | { 169 | locals: { engineName: "ES6 Renderer" }, 170 | partials: { 171 | footer: __dirname + "/partia.html" 172 | } 173 | }, 174 | err => expect(err instanceof Error).to.equal(true) 175 | ).catch(assert); 176 | }); 177 | 178 | }); 179 | 180 | describe("Precompilation", () => { 181 | it("can pre-compile templates when all names are listed", () => { 182 | const text = '${engineName} - The fastest javascript template string engine in the whole ${place}!'; 183 | const precompiled = es6Renderer(text, 'engineName, place'); 184 | const content = precompiled('ES6 Renderer', 'multiverse') 185 | expect(precompiled).to.be.a("function"); 186 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine in the whole multiverse!"); 187 | }); 188 | 189 | it("can precompile templates using default '$' object property", () => { 190 | const text = '${$.engineName} - The fastest javascript template string engine in the whole ${$.place}!'; 191 | const precompiled = es6Renderer(text) 192 | const content = precompiled({ engineName: 'ES6 Renderer', place: 'multiverse' }); 193 | expect(precompiled).to.be.a("function"); 194 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine in the whole multiverse!"); 195 | }); 196 | 197 | it("throws an error on template precompilation failure", () => { 198 | const text = '${engineName} - The fastest javascript template string engine in the whole ${place}!'; 199 | const precompiled = es6Renderer(text, 'engineName'); 200 | const err = precompiled('ES6 Renderer', 'multiverse') 201 | expect(precompiled).to.be.a("function"); 202 | expect(err instanceof Error).to.equal(true); 203 | }); 204 | }); 205 | 206 | describe("Express", () => { 207 | const app = express(); 208 | 209 | app.engine('html', es6Renderer); 210 | app.set('views', __dirname); 211 | app.set('view engine', 'html'); 212 | 213 | it("renders a template file", done => { 214 | app.render( 215 | "index", 216 | { locals: { engineName: "ES6 Renderer", footer: "MIT License" } }, 217 | (err, content) => { 218 | expect(err).to.be.null; 219 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!\nMIT License"); 220 | done(); 221 | } 222 | ); 223 | }); 224 | 225 | it("render partials", done => { 226 | app.render( 227 | "index", 228 | { 229 | locals: { engineName: "ES6 Renderer" }, 230 | partials: { 231 | footer: "partial" 232 | } 233 | }, 234 | (err, content) => { 235 | expect(err).to.be.null; 236 | expect(content).to.equal("ES6 Renderer - The fastest javascript template string engine!\nMIT License"); 237 | done(); 238 | } 239 | ); 240 | }); 241 | 242 | it("throws an error when variable is not found", done => { 243 | app.render( 244 | "index", 245 | { 246 | locals: {}, 247 | partials: { 248 | footer: "partial" 249 | } 250 | }, 251 | (err) => { 252 | expect(err instanceof Error).to.equal(true); 253 | expect(err.message).to.equal('engineName is not defined'); 254 | done(); 255 | } 256 | ); 257 | }); 258 | }); 259 | 260 | }); 261 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | ${engineName} - The fastest javascript template string engine! 2 | ${footer} -------------------------------------------------------------------------------- /test/partial.html: -------------------------------------------------------------------------------- 1 | MIT License --------------------------------------------------------------------------------