When using Bootprint from the command line, you can provide a file with configuration options. The configuration options override the default-options of the module that you specify in the <spec> command-line-parameter. This means, by providing a config-file, you can alter the behaviour defined in this module. You can provide alternative styles or different contents.
The configuration file is a JavaScript file that exports an object matching this extended JSON-schema.
When using Bootprint's JavaScript-API, the same format can be passed to the BootprintBuilder.merge() function.
If you want to change the styling of Bootprint's output, you can configure custom {less}-files:
module.exports = {
less: {
main: [
// Use "require.resolve" to ensure the correct absolute path to the directory.
require.resolve("./theme.less")
],
paths: [
// Require.resolve does not work for directories
require('path').join(__dirname,'less-include')
]
}
}
This configuration will include the file "theme.less" into CSS-generation. The file is included after other less-files. It can be used to redefine variables and style definition from other less files. The module documentation of the bootprint-modules you are using, should include less-variables and styles that can be overridden.
If you need to add include-paths to the less-compiler (e.g. you are including a third party library
that uses @import
statements in their less-files, your can add their import directories
to the paths
so that the included files can be found. This is how the Bootstrap
less files are
included in the bootprint-base
module.
In the bootprint-configuration, you can provide a directory containing partials, for example:
var path = require('path')
module.exports = {
handlebars: {
partials: path.join(__dirname, './partials')
}
}
The partials directory is traversed recursively and all .hbs
-files are registered as partial under
their path relative to the partials
-directory and without the extension. For example,
partials/json-schema/properties.hbs
can be accessed in Handlebars by writing {{>json-schema/properties}}
.
The module you are using already has partials and you can override them by providing a partial file with the
same relative path inside your partials
-directory. For example, if you are using the bootprint-json-schema
module, you can override its partial json-schema/properties
by adding a partials/json-schema/properties.hbs
file to your local directory.
You should be careful overriding partials of other modules. The author should have documented, which partials are meant to be overridden. If you override other partials anyway, you may introduce copy-code and miss bug-fixes later on.
At the moment, the existing modules do not have such a documentation. I hope to add some soon.
You can also replace the whole template and add other templates that are compiled as well.
var path = require('path')
module.exports = {
handlebars: {
templates: path.join(__dirname, './templates')
}
}
If you put an index.html.hbs
-file into the temlates/
-directory, it will override the default template.
If you put an second.html.hbs
-file into this directory, a second.html
-file will be created in your
target diretory.
You can also create a directory-tree with subdirectory containing templates. The tree will be recreated with
the compiled template in the target
-directory
Note: If you feel that the index.html.hbs
provided with bootprint-base
doesn't fit your needs, please let me know!
Maybe we can adapt it to be more flexible.
If your template or your partials require certain Handlebars-helpers, you can provide custom helpers to the configuration:
module.exports = {
handlebars: {
helpers: {
"shout-loud": function (value) {
return value.toUpperCase();
}
}
}
}
Or you can set the path to a JavaScript-module exporting an object of functions
// handlebars/helpers.js
module.exports = {
'shout-loud': function (value) {
return value.toUpperCase()
}
}
// bootprint-configuration
module.exports = {
handlebars: {
helpers: require.resolve('./handlebars/helpers.js')
}
}
Note that we use require.resolve
to reference the helper file and not require
. That way, Bootprint can
register a file-watcher in development mode and automatically update the output when a helper changes.
If one of your helpers already exists in the module you are using, it replaces the original helper.
Usually, if you call a helper in Handlebars using {{helper param1 param2}}
, the helper needs to be a
function(param1, param2, options)
, where options
contains additional information such as named
parameters and block data.
Bootprint provides one more parameter to the helper:
function(param1, param2, options, bootprint)
where
bootprint.engine
contains the active Handlebars engine andbootprint.config
contains the resolved Bootprint configuration
This object is mostly useful, if you create your own Bootprint module: engine allows you to access engine internals (such as the registered partials ) from the helper and config allows you to build configurable templates.
Note: I thought about providing mechanisms and conventions for module-configuration, such as a helper that accesses the Bootprint-configuration in a predefined way. Let me know, if your are in need of such a feature.
Sometimes it is easier to modify the structure of a JSON before applying the Handlebars template than to solve rendering problems within the template.
In such a case, you can include a preprocessor-function in the configuration:
module.exports = {
handlebars: {
/**
* @param {object} obj the input JSON object.
* @return {object|Promise<object>} an object of the promise for an object
**/
preprocessor: function (obj) {
// Call parent preprocessor
var result = this.parent(object)
// Do something to the result
// Return either the result or a promise for the result.
return result
}
}
}
You can also put the preprocessor into its own javascript-file and reference the file from the configuration:
// preprocessor.js
/**
* @param {object} obj the input JSON object.
* @return {object|Promise<object>} an object or the promise for an object
**/
module.exports = function (obj) {
// Call parent preprocessor
var result = this.parent(object);
// Do something to the result
// Return either the result or a promise for the result.
return result;
}
// configuration file
module.exports = {
handlebars: {
preprocessor: require.resolve('./preprocessor.js')
}
}
As with the helpers we use require.resolve
and not require
; Bootprint will require
the file itself. The big advantage is
that in the development mode Bootprint is able to register a file-watcher for the preprocessor-file so that
the output will be automatically regenerated when the preprocessor changes.
Inside Bootprint, the preprocessor is called in a promise-chain, so you can either return a promise or the actual result.
If you are using a module and it already has a preprocessor, you probably want to call it from somewhere in your code.
Otherwise the modules's Handlebars-template might not work anymore. The module's preprocessor
is called the parent-preprocessor
. It is available in the function-context under this.parent
. It is not called
automatically, so you have to call it yourself, if you want to provide your own preprocessor.
If you write a module, you should document what input you expect and what you return, so other people know how to override your preprocessor correctly.