Skip to content

Commit

Permalink
Merge pull request #110 from Financial-Times/matth/engine-tuning
Browse files Browse the repository at this point in the history
Engine tuning
  • Loading branch information
i-like-robots authored Jul 25, 2018
2 parents 1cd87d6 + 39ae717 commit c0ac0b1
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 39 deletions.
2 changes: 1 addition & 1 deletion components/x-teaser/docs/migration-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ The `n-teaser` package uses this functionality to load its internal helper funct
```diff
helpers: {
- nTeaserPresenter: require('@financial-times/n-teaser').presenter
+ ...require('@financial-times/x-handlebars')
+ x: require('@financial-times/x-handlebars')()
}
```

Expand Down
2 changes: 1 addition & 1 deletion packages/x-handlebars/concerns/resolve-local.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
const path = require('path');
module.exports = (moduleId) => path.join(process.cwd(), moduleId);
module.exports = (baseDirectory, moduleId) => path.resolve(baseDirectory, moduleId);
64 changes: 36 additions & 28 deletions packages/x-handlebars/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,42 +2,50 @@ const { render } = require('@financial-times/x-engine');
const resolvePeer = require('./concerns/resolve-peer');
const resolveLocal = require('./concerns/resolve-local');

// This is a regular function expression so that the template context may be shared as "this"
const x = function ({ hash }) {
let moduleId;
const defaults = {
baseDirectory: process.cwd()
};

if (hash.hasOwnProperty('package')) {
moduleId = resolvePeer(`@financial-times/${hash.package}`);
}
// We're exporting a function in case we need to add options or similar features later
module.exports = (userOptions = {}) => {
const options = Object.assign({}, defaults, userOptions);

if (hash.hasOwnProperty('local')) {
moduleId = resolveLocal(`./${hash.local}`);
}
// Return a regular function expression so that the template context may be shared (this)
return function({ hash }) {
let moduleId;

if (!moduleId) {
throw new Error('You must specify a "package" or "local" argument to load a component');
}
if (hash.hasOwnProperty('package')) {
moduleId = resolvePeer(`@financial-times/${hash.package}`);
}

const target = require(moduleId);
if (hash.hasOwnProperty('local')) {
moduleId = resolveLocal(options.baseDirectory, `./${hash.local}`);
}

// TODO: remove this mixin stuff and make the components more easily configurable!
const mixins = {};
if (!moduleId) {
throw new Error('You must specify a "package" or "local" argument to load a component');
}

if (hash.hasOwnProperty('preset') && target.hasOwnProperty('presets')) {
Object.assign(mixins, target.presets[hash.preset]);
}
const target = require(moduleId);

const component = hash.hasOwnProperty('component') ? target[hash.component] : target;
// TODO: remove this mixin stuff and make the components more easily configurable!
const mixins = {};

if (typeof component !== 'function') {
throw Error(`The included component is not a function, it is of type "${typeof component}"`);
}
if (hash.hasOwnProperty('preset') && target.hasOwnProperty('presets')) {
Object.assign(mixins, target.presets[hash.preset]);
}

const props = Object.assign({}, this, mixins, hash);
const component = hash.hasOwnProperty('component') ? target[hash.component] : target;

// "this" is the current Handlebars context
return render(component(props));
};
const type = typeof component;

if (type !== 'function') {
throw TypeError(`The included component is not a function, it is of type "${type}"`);
}

// Export an object so that we can control the helper name and append new helpers if needed
module.exports = { x };
// "this" is the current Handlebars context
const props = Object.assign({}, this, mixins, hash);

return render(component(props));
};
};
29 changes: 20 additions & 9 deletions packages/x-handlebars/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,50 @@ This module is requires Node 6+ and is distributed on npm.
npm install -S @financial-times/x-handlebars
```

To use the `x-handlebars` helper functions in your application views you must first register them with Handlebars using the `registerHelper` method. Please note that this module exports an object so you don't need to name them individually:
To use the `x-handlebars` helper in your application views you must first register it with Handlebars. To do this you can use the `registerHelper` method, providing a helper name as the first argument (we recommend `x`) and calling the `xHandlebars` function:

```js
const helpers = require('@financial-times/x-handlebars');
const xHandlebars = require('@financial-times/x-handlebars');
const handlebars = require('handlebars');

handlebars.registerHelper(helpers);
handlebars.registerHelper('x', xHandlebars());
```

If you are building an Express app using [n-ui][n-ui] you can register the helper functions on application startup. Please note that if you are already registering helpers then you will need to merge the object exported by `x-handlebars` in with your other configuration:
If you are building an Express app using [n-ui][n-ui] you can register the helper functions on application startup. Please note that if you are already registering helpers then you may need to merge your existing configuration:

```js
const xHandlebars = require('@financial-times/x-handlebars');
const express = require('@financial-times/n-ui');

const app = express({
helpers: require('@financial-times/x-handlebars')
helpers: {
x: xHandlebars()
}
});
```

This module will install the [x-engine][x-engine] module as a dependency to perform the rendering of `x-` components. Please refer to the x-engine documentation to setup your application.
An options object may be provided to the `xHandlebars` function when called. The options and their defaults are shown below:

```js
xHandlebars({
baseDirectory: process.cwd()
});
```

This module will install the [x-engine][x-engine] module as a dependency to perform the rendering of `x-` components. Please refer to the x-engine documentation to setup your application with `x-engine`.

[n-ui]: https://github.com/Financial-Times/n-ui/
[x-engine]: https://github.com/Financial-Times/x-dash/tree/master/packages/x-engine

## Usage

A single helper function (`x`) will be registered to load x-dash component packages or local compatible modules.
This package provides a single helper function able to load x-dash component packages or local compatible modules.

Installed packages will be loaded from the `@financial-times` scope and are specified using the `package` argument.

Local modules are resolved relative to the project root and are specified using the `local` argument.
Local modules are resolved relative to the configured base directory and are specified using the `local` argument.

If a module has multiple named exports then the specific function to use may be specified with the `component` argument.
If a module has multiple named exports then the specific property to use may be specified with the `component` argument.

For example, to render a teaser component from the [x-teaser package][teaser]:

Expand Down

0 comments on commit c0ac0b1

Please sign in to comment.