New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

vision

Package Overview
Dependencies
Maintainers
2
Versions
29
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

vision - npm Package Compare versions

Comparing version 2.0.1 to 3.0.0

examples/ejs/basic.js

40

examples/cms/server.js

@@ -6,2 +6,3 @@ // Load modules

var Pages = require('./pages');
var Vision = require('../..');

@@ -59,17 +60,30 @@

server.connection({ port: 8000, state: { ignoreErrors: true } });
server.register(Vision, function (err) {
server.views({
engines: { html: require('handlebars') },
path: Path.join(__dirname, 'views'),
layout: true,
partialsPath: Path.join(__dirname, 'views', 'partials')
if (err) {
throw err;
}
server.views({
engines: { html: require('handlebars') },
path: Path.join(__dirname, 'views'),
layout: true,
partialsPath: Path.join(__dirname, 'views', 'partials')
});
server.route({ method: 'GET', path: '/', handler: getPages });
server.route({ method: 'GET', path: '/pages/{page}', handler: getPage });
server.route({ method: 'GET', path: '/create', handler: view('create') });
server.route({ method: 'POST', path: '/create', handler: createPage });
server.route({ method: 'GET', path: '/pages/{page}/edit', handler: showEditForm });
server.route({ method: 'POST', path: '/pages/{page}/edit', handler: updatePage });
server.start(function (err) {
if (err) {
throw err;
}
console.log('Server is listening at ' + server.info.uri);
});
});
server.route({ method: 'GET', path: '/', handler: getPages });
server.route({ method: 'GET', path: '/pages/{page}', handler: getPage });
server.route({ method: 'GET', path: '/create', handler: view('create') });
server.route({ method: 'POST', path: '/create', handler: createPage });
server.route({ method: 'GET', path: '/pages/{page}/edit', handler: showEditForm });
server.route({ method: 'POST', path: '/pages/{page}/edit', handler: updatePage });
server.start();
};

@@ -76,0 +90,0 @@

// Load modules
var Hapi = require('hapi');
var Vision = require('../..');

@@ -14,3 +15,3 @@

reply.view('basic/index', {
title: 'examples/views/handlebars/basic.js | Hapi ' + Hapi.version,
title: 'examples/views/handlebars/basic.js | Hapi ' + request.server.version,
message: 'Hello World!'

@@ -25,10 +26,23 @@ });

server.connection({ port: 8000 });
server.register(Vision, function (err) {
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates'
if (err) {
throw err;
}
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates'
});
server.route({ method: 'GET', path: '/', handler: handler });
server.start(function (err) {
if (err) {
throw err;
}
console.log('Server is listening at ' + server.info.uri);
});
});
server.route({ method: 'GET', path: '/', handler: handler });
server.start();
};

@@ -35,0 +49,0 @@

// Load modules
var Hapi = require('hapi');
var Vision = require('../..');

@@ -14,3 +15,3 @@

reply.view('withLayout/index', {
title: 'examples/views/handlebars/layout.js | Hapi ' + Hapi.version,
title: 'examples/views/handlebars/layout.js | Hapi ' + request.server.version,
message: 'Hello World!\n'

@@ -25,11 +26,24 @@ });

server.connection({ port: 8000 });
server.register(Vision, function (err) {
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates',
layout: true
if (err) {
throw err;
}
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates',
layout: true
});
server.route({ method: 'GET', path: '/', handler: handler });
server.start(function (err) {
if (err) {
throw err;
}
console.log('Server is listening at ' + server.info.uri);
});
});
server.route({ method: 'GET', path: '/', handler: handler });
server.start();
};

@@ -36,0 +50,0 @@

// Load modules
var Hapi = require('hapi');
var Vision = require('../..');

@@ -14,3 +15,3 @@

reply.view('withPartials/index', {
title: 'examples/views/handlebars/partials.js | Hapi ' + Hapi.version,
title: 'examples/views/handlebars/partials.js | Hapi ' + request.server.version,
message: 'Hello World!\n'

@@ -25,11 +26,24 @@ });

server.connection({ port: 8000 });
server.register(Vision, function (err) {
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates',
partialsPath: __dirname + '/templates/withPartials'
if (err) {
throw err;
}
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates',
partialsPath: __dirname + '/templates/withPartials'
});
server.route({ method: 'GET', path: '/', handler: handler });
server.start(function (err) {
if (err) {
throw err;
}
console.log('Server is listening at ' + server.info.uri);
});
});
server.route({ method: 'GET', path: '/', handler: handler });
server.start();
};

@@ -36,0 +50,0 @@

// Load modules
var Hapi = require('hapi');
var Vision = require('../..');

@@ -14,3 +15,3 @@

reply.view('index', {
title: 'examples/views/jade/index.js | Hapi ' + Hapi.version,
title: 'examples/views/jade/index.js | Hapi ' + request.server.version,
message: 'Index - Hello World!'

@@ -23,3 +24,3 @@ });

reply.view('about', {
title: 'examples/views/jade/index.js | Hapi ' + Hapi.version,
title: 'examples/views/jade/index.js | Hapi ' + request.server.version,
message: 'About - Hello World!'

@@ -34,14 +35,27 @@ });

server.connection({ port: 8000 });
server.register(Vision, function (err) {
server.views({
engines: { jade: require('jade') },
path: __dirname + '/templates',
compileOptions: {
pretty: true
if (err) {
throw err;
}
server.views({
engines: { jade: require('jade') },
path: __dirname + '/templates',
compileOptions: {
pretty: true
}
});
server.route({ method: 'GET', path: '/', handler: rootHandler });
server.route({ method: 'GET', path: '/about', handler: aboutHandler });
server.start(function (err) {
if (err) {
throw err;
}
console.log('Server is listening at ' + server.info.uri);
});
});
server.route({ method: 'GET', path: '/', handler: rootHandler });
server.route({ method: 'GET', path: '/about', handler: aboutHandler });
server.start();
};

@@ -48,0 +62,0 @@

// Load modules
var Hapi = require('hapi');
var Vision = require('../..');

@@ -10,11 +11,11 @@

var ctx = {
title: 'examples/views/mixed | Hapi ' + Hapi.version,
message: 'Hello World!'
var indexHandler = function (request, reply) {
reply.view('index.html');
};
var oneHandler = function (request, reply) {
reply.view('index.jade', ctx);
reply.view('index.jade');
};

@@ -24,3 +25,3 @@

reply.view('handlebars.html', ctx);
reply.view('handlebars.html');
};

@@ -33,14 +34,32 @@

server.connection({ port: 8000 });
server.register(Vision, function (err) {
server.views({
engines: {
'html': require('handlebars'),
'jade': require('jade')
},
path: __dirname + '/templates'
if (err) {
throw err;
}
server.views({
engines: {
'html': require('handlebars'),
'jade': require('jade')
},
path: __dirname + '/templates',
context: {
title: 'examples/views/mixed | Hapi ' + server.version,
message: 'Hello World!'
}
});
server.route({ method: 'GET', path: '/', handler: indexHandler });
server.route({ method: 'GET', path: '/one', handler: oneHandler });
server.route({ method: 'GET', path: '/two', handler: twoHandler });
server.start(function (err) {
if (err) {
throw err;
}
console.log('Server is listening at ' + server.info.uri);
});
});
server.route({ method: 'GET', path: '/one', handler: oneHandler });
server.route({ method: 'GET', path: '/two', handler: twoHandler });
server.start();
};

@@ -47,0 +66,0 @@

@@ -28,3 +28,3 @@ // Load modules

exports.register = function (server, options, next) {
exports.register = function (server, pluginOptions, next) {

@@ -47,12 +47,5 @@ server.decorate('server', 'views', function (options) {

server.decorate('server', 'render', function (template, context, options, callback) {
server.decorate('server', 'render', internals.render);
server.decorate('request', 'render', internals.render);
callback = (typeof callback === 'function' ? callback : options);
options = (options === callback ? {} : options);
var vision = (this.realm.plugins.vision || this.root.realm.plugins.vision || {});
Hoek.assert(vision.manager, 'Missing views manager');
return vision.manager.render(template, context, options, callback);
});
server.handler('view', internals.handler);

@@ -75,2 +68,15 @@

internals.render = function (template, context, options, callback) {
callback = (typeof callback === 'function' ? callback : options);
options = (options === callback ? {} : options);
var isServer = (typeof this.route === 'function');
var server = (isServer ? this : this.server);
var vision = ((!isServer ? this.route.realm.plugins.vision : null) || server.realm.plugins.vision || server.root.realm.plugins.vision || {});
Hoek.assert(vision.manager, 'Missing views manager');
return vision.manager.render(template, context, options, callback);
};
internals.handler = function (route, options) {

@@ -77,0 +83,0 @@

@@ -159,2 +159,5 @@ // Load modules

// When a prepare function is provided, state needs to be initialized before trying to compile and render
engine.ready = !(engine.module.prepare && typeof engine.module.prepare === 'function');
// Load partials and helpers

@@ -270,37 +273,49 @@

options = options || {};
this._prepare(filename, options, function (err, compiled) {
if (this._context) {
var base = typeof this._context === 'function' ? this._context() : this._context;
if (context) {
base = Hoek.shallow(base);
var keys = Object.keys(context);
for (var i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
base[key] = context[key];
}
if (err) {
return callback(err);
}
context = base;
}
self._render(compiled, context, function (err, rendered) {
context = context || {};
if (err) {
return callback(err);
}
var engine = null;
return callback(null, rendered, compiled.settings);
});
});
};
var fileExtension = Path.extname(filename).slice(1);
internals.Manager.prototype._prepare = function (template, options, callback) {
var self = this;
options = options || {};
var fileExtension = Path.extname(template).slice(1);
var extension = fileExtension || this._defaultExtension;
if (!extension) {
return callback(Boom.badImplementation('Unknown extension and no defaultExtension configured for view template: ' + filename));
return callback(Boom.badImplementation('Unknown extension and no defaultExtension configured for view template: ' + template));
}
engine = this._engines[extension];
var engine = this._engines[extension];
if (!engine) {
return callback(Boom.badImplementation('No view engine found for file: ' + filename));
return callback(Boom.badImplementation('No view engine found for file: ' + template));
}
var settings = Hoek.applyToDefaults(engine.config, options);
template = template + (fileExtension ? '' : engine.suffix);
this._path(filename + (fileExtension ? '' : engine.suffix), settings, false, function (err, templatePath) {
// Engine is ready to render
if (engine.ready) {
return this._prepareTemplates(template, engine, options, callback);
}
// Engine needs initialization
return this._prepareEngine(engine, function (err) {
if (err) {

@@ -310,31 +325,60 @@ return callback(err);

self._compile(templatePath, engine, settings, function (err, compiled) {
return self._prepareTemplates(template, engine, options, callback);
});
};
internals.Manager.prototype._prepareEngine = function (engine, next) {
// _prepareEngine can only be invoked when the prepare function is defined
try {
return engine.module.prepare(engine.config, function (err) {
if (err) {
return callback(err);
return next(err);
}
// No layout
engine.ready = true;
return next();
});
}
catch (err) {
return next(err);
}
};
if (!settings.layout) {
compiled(context, settings.runtimeOptions, function (err, rendered) {
if (err) {
return callback(Boom.badImplementation(err.message, err));
}
internals.Manager.prototype._prepareTemplates = function (template, engine, options, callback) {
return callback(null, rendered, settings);
});
var self = this;
return;
var compiled = {
settings: Hoek.applyToDefaults(engine.config, options)
};
this._path(template, compiled.settings, false, function (err, templatePath) {
if (err) {
return callback(err);
}
self._compile(templatePath, engine, compiled.settings, function (err, compiledTemplate) {
if (err) {
return callback(err);
}
// With layout
compiled.template = compiledTemplate;
if (context.hasOwnProperty(settings.layoutKeyword)) {
return callback(Boom.badImplementation('settings.layoutKeyword conflict', { context: context, keyword: settings.layoutKeyword }));
// No layout
if (!compiled.settings.layout) {
return callback(null, compiled);
}
self._path((settings.layout === true ? 'layout' : settings.layout) + engine.suffix, settings, true, function (err, layoutPath) {
// With layout
self._path((compiled.settings.layout === true ? 'layout' : compiled.settings.layout) + engine.suffix, compiled.settings, true, function (err, layoutPath) {
if (err) {

@@ -344,3 +388,3 @@ return callback(err);

self._compile(layoutPath, engine, settings, function (err, layout) {
self._compile(layoutPath, engine, compiled.settings, function (err, layout) {

@@ -351,20 +395,4 @@ if (err) {

compiled(context, settings.runtimeOptions, function (err, rendered) {
if (err) {
return callback(Boom.badImplementation(err.message, err));
}
context[settings.layoutKeyword] = rendered;
layout(context, settings.runtimeOptions, function (err, rendered) {
delete context[settings.layoutKeyword];
if (err) {
return callback(Boom.badImplementation(err.message, err));
}
return callback(null, rendered, settings);
});
});
compiled.layout = layout;
return callback(null, compiled);
});

@@ -430,2 +458,55 @@ });

internals.Manager.prototype._render = function (compiled, context, callback) {
var self = this;
if (this._context) {
var base = typeof this._context === 'function' ? this._context() : this._context;
if (context) {
base = Hoek.shallow(base);
var keys = Object.keys(context);
for (var i = 0, il = keys.length; i < il; ++i) {
var key = keys[i];
base[key] = context[key];
}
}
context = base;
}
context = context || {};
if (context.hasOwnProperty(compiled.settings.layoutKeyword)) {
return callback(Boom.badImplementation('settings.layoutKeyword conflict', { context: context, keyword: compiled.settings.layoutKeyword }));
}
compiled.template(context, compiled.settings.runtimeOptions, function (err, renderedContent) {
if (err) {
return callback(Boom.badImplementation(err.message, err));
}
// No layout
if (!compiled.layout) {
return callback(null, renderedContent);
}
// With layout
context[compiled.settings.layoutKeyword] = renderedContent;
compiled.layout(context, compiled.settings.runtimeOptions, function (err, renderedWithLayout) {
delete context[compiled.settings.layoutKeyword];
if (err) {
return callback(Boom.badImplementation(err.message, err));
}
return callback(null, renderedWithLayout);
});
});
};
internals.path = function (base, path, file) {

@@ -488,3 +569,3 @@

return request.generateResponse(source, { variety: 'view', marshal: internals.marshal });
return request.generateResponse(source, { variety: 'view', marshal: internals.marshal, prepare: internals.prepare });
};

@@ -497,3 +578,3 @@

manager.render(response.source.template, response.source.context, response.source.options, function (err, rendered, config) {
manager._render(response.source.compiled, response.source.context, function (err, rendered) {

@@ -504,2 +585,4 @@ if (err) {

var config = response.source.compiled.settings;
if (!response.headers['content-type']) {

@@ -514,1 +597,16 @@ response.type(config.contentType);

};
internals.prepare = function (response, callback) {
var manager = response.source.manager;
manager._prepare(response.source.template, response.source.options, function (err, compiled) {
if (err) {
return callback(err);
}
response.source.compiled = compiled;
return callback(response);
});
};
{
"name": "vision",
"description": "Templates rendering plugin support for hapi.js",
"version": "2.0.1",
"version": "3.0.0",
"repository": "git://github.com/hapijs/vision",
"main": "index",
"main": "lib/index.js",
"keywords": [

@@ -24,16 +24,17 @@ "view",

"code": "1.x.x",
"hapi": "8.x.x",
"ejs": "2.x.x",
"handlebars": "3.x.x",
"hapi": "9.x.x",
"jade": "1.x.x",
"lab": "5.x.x",
"handlebars": "3.x.x",
"jade": "1.x.x"
"mustache": "2.x.x",
"nunjucks": "1.x.x",
"hapi-react-views": "3.x.x",
"react": "0.x.x"
},
"scripts": {
"test": "make test-cov"
"test": "lab -a code -t 100 -L",
"test-cov-html": "lab -a code -r html -o coverage.html"
},
"licenses": [
{
"type": "BSD",
"url": "http://github.com/hapijs/vision/raw/master/LICENSE"
}
]
"license": "BSD-3-Clause"
}

@@ -7,2 +7,450 @@ #vision

Lead Maintainer - [Eran Hammer](https://github.com/hueniverse)
Lead Maintainer - [Jeffrey Jagoda](https://github.com/jagoda)
**vision** decorates the [server](https://github.com/hapijs/hapi/blob/master/API.md#server) and
[reply](https://github.com/hapijs/hapi/blob/master/API.md#reply-interface) interfaces with additional
methods for managing view engines that can be used to render templated responses. **vision** also
provides a built-in [handler](https://github.com/hapijs/hapi/blob/master/API.md#serverhandlername-method)
implementation for creating templated responses.
```js
var server = new Hapi.Server();
server.connection({ port: 8080 });
server.register(require('vision'), function (err) {
if (err) {
console.log("Failed to load vision.");
}
});
```
**NOTE:** Vision is included with and loaded by default in Hapi < 9.0.
- [Examples](#examples)
- [EJS](#ejs)
- [Handlebars](#handlebars)
- [Jade](#jade)
- [Mustache](#mustache)
- [Nunjucks](#nunjucks)
- [Usage](#usage)
- [`server.views(options)`](#serverviewsoptions)
- [`server.render(template, context, [options], callback)`](#serverrendertemplate-context-options-callback)
- [`reply.view(template, [context, [options]])`](#replyviewtemplate-context-options)
- [The `view` handler](#the-view-handler)
## Examples
**vision** is compatible with most major templating engines out of the box. Engines that don't follow
the normal API pattern can still be used by mapping their API to the **vision** API. Working code for
the following examples can be found in the [examples directory](./examples).
### EJS
```js
var server = new Hapi.Server();
server.connection({ port: 8000 });
var rootHandler = function (request, reply) {
reply.view('index', {
title: 'examples/views/ejs/index.js | Hapi ' + request.server.version,
message: 'Index - Hello World!'
});
};
server.register(require('vision'), function (err) {
if (err) {
throw err;
}
server.views({
engines: { ejs: require('ejs') },
relativeTo: __dirname,
path: 'templates'
});
server.route({ method: 'GET', path: '/', handler: rootHandler });
});
```
### Handlebars
```js
var server = new Hapi.Server();
server.connection({ port: 8000 });
var handler = function (request, reply) {
reply.view('basic/index', {
title: 'examples/views/handlebars/basic.js | Hapi ' + request.server.version,
message: 'Hello World!'
});
};
server.register(require('vision'), function (err) {
if (err) {
throw err;
}
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates'
});
server.route({ method: 'GET', path: '/', handler: handler });
});
```
### Jade
```js
var server = new Hapi.Server();
server.connection({ port: 8000 });
var rootHandler = function (request, reply) {
reply.view('index', {
title: 'examples/views/jade/index.js | Hapi ' + request.server.version,
message: 'Index - Hello World!'
});
};
var aboutHandler = function (request, reply) {
reply.view('about', {
title: 'examples/views/jade/index.js | Hapi ' + request.server.version,
message: 'About - Hello World!'
});
};
server.register(require('vision'), function (err) {
if (err) {
throw err;
}
server.views({
engines: { jade: require('jade') },
path: __dirname + '/templates',
compileOptions: {
pretty: true
}
});
server.route({ method: 'GET', path: '/', handler: rootHandler });
server.route({ method: 'GET', path: '/about', handler: aboutHandler });
});
```
### Mustache
```js
var server = new Hapi.Server();
server.connection({ port: 8000 });
var rootHandler = function (request, reply) {
reply.view('index', {
title: 'examples/views/mustache/index.js | Hapi ' + request.server.version,
message: 'Index - Hello World!'
});
};
server.register(require('vision'), function (err) {
if (err) {
throw err;
}
server.views({
engines: {
html: {
compile: function (template) {
Mustache.parse(template);
return function (context) {
return Mustache.render(template, context);
};
}
}
},
relativeTo: __dirname,
path: 'templates'
});
server.route({ method: 'GET', path: '/', handler: rootHandler });
});
```
### Nunjucks
```js
var server = new Hapi.Server();
server.connection({ port: 8000 });
var rootHandler = function (request, reply) {
reply.view('index', {
title: 'examples/views/nunjucks/index.js | Hapi ' + request.server.version,
message: 'Index - Hello World!'
});
};
server.register(require('vision'), function (err) {
if (err) {
throw err;
}
server.views({
engines: {
html: {
compile: function (src, options) {
var template = Nunjucks.compile(src, options.environment);
return function (context) {
return template.render(context);
};
},
prepare: function (options, next) {
options.compileOptions.environment = Nunjucks.configure(options.path, { watch : false });
return next();
}
}
},
path: Path.join(__dirname, 'templates')
});
server.route({ method: 'GET', path: '/', handler: rootHandler });
});
```
## Usage
Most interaction with **vision** is done via the [server](https://github.com/hapijs/hapi/blob/master/API.md#server)
and [reply](https://github.com/hapijs/hapi/blob/master/API.md#reply-interface) interfaces. When the
**vision** plugin is registered, the base [Hapi APIs](https://github.com/hapijs/hapi/blob/master/API.md)
are augmented with the following:
### `server.views(options)`
Initializes the server views manager where:
- `options` - a configuration object with the following:
- `engines` - required object where each key is a file extension (e.g. 'html', 'hbr'), mapped
to the npm module used for rendering the templates. Alternatively, the extension can be
mapped to an object with the following options:
- `module` - the npm module used for rendering the templates. The module object must
contain the `compile()` function:
- `compile()` - the rendering function. The required function signature depends on the
`compileMode` settings. If the `compileMode` is `'sync'`, the signature is
`compile(template, options)`, the return value is a function with signature
`function(context, options)`, and the method is allowed to throw errors. If the
`compileMode` is `'async'`, the signature is `compile(template, options, callback)`
where `callback` has the signature `function(err, compiled)` where `compiled` is a
function with signature `function(context, options, callback)` and `callback` has the
signature `function(err, rendered)`.
- `prepare(config, next)` - initializes additional engine state.
The `config` object is the engine configuration object allowing updates to be made.
This is useful for engines like Nunjucks that rely on additional state for rendering.
`next` has the signature `function(err)`.
- `registerPartial(name, src)` - registers a partial for use during template rendering.
The `name` is the partial path that templates should use to reference the partial and
`src` is the uncompiled template string for the partial.
- `registerHelper(name, helper)` - registers a helper for use during template rendering.
The `name` is the name that templates should use to reference the helper and `helper`
is the function that will be invoked when the helper is called.
- any of the `views` options listed below (except `defaultExtension`) to override the
defaults for a specific engine.
- `defaultExtension` - defines the default filename extension to append to template names when
multiple engines are configured and not explicit extension is provided for a given template.
No default value.
- `path` - the root file path used to resolve and load the templates identified when calling
[`reply.view()`](https://github.com/hapijs/hapi/blob/master/API.md#replyviewtemplate-context-options).
Defaults to current working directory.
- `partialsPath` - the root file path where partials are located. Partials are small segments
of template code that can be nested and reused throughout other templates. Defaults to no
partials support (empty path).
- `helpersPath` - the directory path where helpers are located. Helpers are functions used
within templates to perform transformations and other data manipulations using the template
context or other inputs. Each '.js' file in the helpers directory is loaded and the file name
is used as the helper name. The files must export a single method with the signature
`function(context)` and return a string. Sub-folders are not supported and are ignored.
Defaults to no helpers support (empty path). Note that jade does not support loading helpers
this way.
- `relativeTo` - a base path used as prefix for `path` and `partialsPath`. No default.
- `layout` - if set to `true` or a layout filename, layout support is enabled. A layout is a
single template file used as the parent template for other view templates in the same engine.
If `true`, the layout template name must be 'layout.ext' where 'ext' is the engine's
extension. Otherwise, the provided filename is suffixed with the engine's extension and
loaded. Disable `layout` when using Jade as it will handle including any layout files
independently. Defaults to `false`.
- `layoutPath` - the root file path where layout templates are located (using the `relativeTo`
prefix if present). Defaults to `path`.
- `layoutKeyword` - the key used by the template engine to denote where primary template
content should go. Defaults to `'content'`.
- `encoding` - the text encoding used by the templates when reading the files and outputting
the result. Defaults to `'utf8'`.
- `isCached` - if set to `false`, templates will not be cached (thus will be read from file on
every use). Defaults to `true`.
- `allowAbsolutePaths` - if set to `true`, allows absolute template paths passed to
[`reply.view()`](https://github.com/hapijs/hapi/blob/master/API.md#replyviewtemplate-context-options).
Defaults to `false`.
- `allowInsecureAccess` - if set to `true`, allows template paths passed to
[`reply.view()`](https://github.com/hapijs/hapi/blob/master/API.md#replyviewtemplate-context-options)
to contain '../'. Defaults to `false`.
- `compileOptions` - options object passed to the engine's compile function. Defaults to empty
options `{}`.
- `runtimeOptions` - options object passed to the returned function from the compile operation.
Defaults to empty options `{}`.
- `contentType` - the content type of the engine results. Defaults to `'text/html'`.
- `compileMode` - specify whether the engine `compile()` method is `'sync'` or `'async'`.
Defaults to `'sync'`.
- `context` - a global context used with all templates. The global context option can be either
an object or a function that takes no arguments and returns a context object. When rendering
views, the global context will be merged with any context object specified on the handler or
using [`reply.view()`](https://github.com/hapijs/hapi/blob/master/API.md#replyviewtemplate-context-options).
When multiple context objects are used, values from the global context always have lowest precedence.
When [`server.views()`](https://github.com/hapijs/hapi/blob/master/API.md#serverviewsoptions) is called within a
plugin, the views manager is only available to [plugins](https://github.com/hapijs/hapi/blob/master/API.md#plugins)
methods.
### `server.render(template, context, [options], callback)`
Utilizes the server views manager to render a template where:
- `template` - the template filename and path, relative to the views manager templates path (`path`
or `relativeTo`).
- `context` - optional object used by the template to render context-specific result. Defaults to
no context (`{}`).
- `options` - optional object used to override the views manager configuration.
- `callback` - the callback function with signature `function (err, rendered, config)` where:
- `err` - the rendering error if any.
- `rendered` - the result view string.
- `config` - the configuration used to render the template.
```js
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 80 });
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates'
});
var context = {
title: 'Views Example',
message: 'Hello, World'
};
server.render('hello', context, function (err, rendered, config) {
console.log(rendered);
});
```
### `reply.view(template, [context, [options]])`
Concludes the handler activity by returning control over to the router with a templatized view
response where:
- `template` - the template filename and path, relative to the templates path configured via the
server views manager.
- `context` - optional object used by the template to render context-specific result. Defaults to
no context `{}`.
- `options` - optional object used to override the server's views manager configuration for this
response. Cannot override `isCached`, `partialsPath`, or `helpersPath` which are only loaded at
initialization.
Returns a [response object](https://github.com/hapijs/hapi/blob/master/API.md#response-object).
The [response flow control rules](https://github.com/hapijs/hapi/blob/master/API.md#flow-control) apply.
```js
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 80 });
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates'
});
var handler = function (request, reply) {
var context = {
title: 'Views Example',
message: 'Hello, World'
};
return reply.view('hello', context);
};
server.route({ method: 'GET', path: '/', handler: handler });
```
**templates/hello.html**
```html
<!DOCTYPE html>
<html>
<head>
<title>{{title}}</title>
</head>
<body>
<div>
<h1>{{message}}</h1>
</div>
</body>
</html>
```
### The `view` handler
The `view` handler can be used with routes registered in the same realm as the view manager. The
handler takes an `options` parameter that can be either a string or an object. When the `options`
parameter is a string, it should be the filename and path of the template relative to the templates
path configured via the views manager. When the `options` parameter is an object, it may have the
following keys:
- `template` - the template filename and path, relative to the templates path configured via the
server views manager.
- `context` - optional object used by the template to render context-specific result. Defaults to
no context `{}`.
- `options` - optional object used to override the server's views manager configuration for this
response. Cannot override `isCached`, `partialsPath`, or `helpersPath` which are only loaded at
initialization.
The rendering `context` contains the `params`, `payload`, `query`, and `pre` values from the
[request](https://github.com/hapijs/hapi/blob/master/API.md#request-properties) by default (these
can be overriden by values explicitly set via the `options`).
```js
var Hapi = require('hapi');
var server = new Hapi.Server();
server.connection({ port: 80 });
server.views({
engines: { html: require('handlebars') },
path: __dirname + '/templates'
});
server.route({
method: 'GET',
path: '/',
handler: {
view: {
template: 'hello',
context: {
title: 'Views Example',
message: 'Hello, World'
}
}
}
});
```

@@ -30,3 +30,3 @@ // Load modules

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -52,3 +52,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -71,3 +71,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -96,3 +96,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -127,3 +127,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -147,3 +147,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -167,3 +167,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -190,3 +190,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -217,3 +217,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -245,3 +245,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true, debug: false });
var server = new Hapi.Server({ debug: false });
server.register(Vision, Hoek.ignore);

@@ -270,3 +270,3 @@ server.connection();

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -290,3 +290,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -335,3 +335,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -374,3 +374,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -422,3 +422,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -440,3 +440,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.register(Vision, Hoek.ignore);

@@ -449,2 +449,45 @@ expect(function () {

});
it('renders view (plugin request)', function (done) {
var test = function (server, options, next) {
server.views({
engines: { 'html': Handlebars },
relativeTo: Path.join(__dirname, '/templates/plugin')
});
server.route({
method: 'GET',
path: '/view',
handler: function (request, reply) {
request.render('test', { message: 'steve' }, function (err, rendered, config) {
return reply(rendered);
});
}
});
return next();
};
test.attributes = {
name: 'test'
};
var server = new Hapi.Server();
server.connection();
server.register(Vision, Hoek.ignore);
server.register(test, function (err) {
expect(err).to.not.exist();
server.inject('/view', function (res) {
expect(res.result).to.equal('<h1>steve</h1>');
done();
});
});
});
});

@@ -495,3 +538,3 @@

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -503,9 +546,9 @@ server.register(Vision, Hoek.ignore);

expect(err).to.not.exist();
server.inject('/view', function (res) {
server.inject('/view', function (viewResponse) {
expect(res.result).to.equal('<h1>viewing it</h1>');
expect(viewResponse.result).to.equal('<h1>viewing it</h1>');
server.inject('/ext', function (res) {
server.inject('/ext', function (extResponse) {
expect(res.result).to.equal('<h1>grabbed</h1>');
expect(extResponse.result).to.equal('<h1>grabbed</h1>');
done();

@@ -542,3 +585,3 @@ });

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -578,3 +621,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.connection();

@@ -605,3 +648,3 @@ server.register(Vision, Hoek.ignore);

var server = new Hapi.Server({ minimal: true });
var server = new Hapi.Server();
server.register(Vision, Hoek.ignore);

@@ -608,0 +651,0 @@ server.views({ engines: { 'html': Handlebars } });

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc