Skip to content

Latest commit

 

History

History
242 lines (171 loc) · 7.95 KB

config.md

File metadata and controls

242 lines (171 loc) · 7.95 KB

Configuration

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.

Providing themes with custom {less}-files.

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.

Overriding and adding partials

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.

Overriding the main template

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.

Providing custom helpers

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 and
  • bootprint.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.

Preprocessor

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.