@unic/estatico-handlebars

0.0.11 • Public • Published

@unic/estatico-handlebars

Transforms Handlebars to HTML.

Installation

$ npm install --save-dev @unic/estatico-handlebars

Usage

const gulp = require('gulp');
const path = require('path');
const env = require('minimist')(process.argv.slice(2));

/**
 * HTML task
 * Transforms Handlebars to HTML
 *
 * Using `--watch` (or manually setting `env` to `{ watch: true }`) starts file watcher
 * When combined with `--skipBuild`, the task will not run immediately but only after changes
 *
 * Using `-LLLL` will display debug info like the data used for every template
 */
gulp.task('html', () => {
  const task = require('@unic/estatico-handlebars');
  const estaticoWatch = require('@unic/estatico-watch');
  const { readFileSyncCached } = require('@unic/estatico-utils');

  const instance = task({
    src: [
      './src/*.hbs',
      './src/pages/**/*.hbs',
      './src/demo/pages/**/*.hbs',
      '!./src/demo/pages/handlebars/*.hbs',
      './src/modules/**/!(_)*.hbs',
      './src/demo/modules/**/!(_)*.hbs',
      './src/preview/styleguide/*.hbs',
      '!./src/preview/styleguide/colors.hbs',
    ],
    srcBase: './src',
    dest: './dist',
    watch: {
      src: [
        './src/**/*.hbs',
        './src/**/*.data.js',
      ],
      name: 'html',
      dependencyGraph: {
        srcBase: './',
        resolver: {
          hbs: {
            match: /{{(?:>|#extend)[\s-]*["|']?([^"\s(]+).*?}}/g,
            resolve: (match /* , filePath */) => {
              if (!match[1]) {
                return null;
              }

              let resolvedPath = path.resolve('./src', match[1]);

              // Add extension
              resolvedPath = `${resolvedPath}.hbs`;

              return resolvedPath;
            },
          },
          js: {
            match: /require\('(.*?\.data\.js)'\)/g,
            resolve: (match, filePath) => {
              if (!match[1]) {
                return null;
              }

              return path.resolve(path.dirname(filePath), match[1]);
            },
          },
        },
      },
      watcher: estaticoWatch,
    },
    plugins: {
      clone: null,
      handlebars: {
        partials: [
          './src/**/*.hbs',
        ],
      },
      // Wrap with module layout
      transformBefore: (file) => {
        if (file.path.match(/(\\|\/)modules(\\|\/)/)) {
          return Buffer.from(readFileSyncCached('./src/preview/layouts/module.hbs'));
        }

        return file.contents;
      },
      // Relativify absolute paths
      transformAfter: (file) => {
        let content = file.contents.toString();
        let relPathPrefix = path.join(path.relative(file.path, './src'));

        relPathPrefix = relPathPrefix
          .replace(new RegExp(`\\${path.sep}g`), '/') // Normalize path separator
          .replace(/\.\.$/, ''); // Remove trailing ..

        content = content.replace(/('|")\/(?!\^)/g, `$1${relPathPrefix}`);

        content = Buffer.from(content);

        return content;
      },
    },
  }, env);
  
  // Don't immediately run task when skipping build
  if (env.watch && env.skipBuild) {
    return instance;
  }

  return instance();
});

Run task (assuming the project's package.json specifies "scripts": { "gulp": "gulp" }): $ npm run gulp html

See possible flags specified above.

API

plugin(options, env) => taskFn

options

src (required)

Type: Array or String
Default: null

Passed to gulp.src.

srcBase (required)

Type: String
Default: null

Passed as base option to gulp.src.

dest (required)

Type: String
Default: null

Passed to gulp.dest.

watch

Type: Object
Default: null

Passed to file watcher when --watch is used.

plugins

Type: Object

plugins.handlebars

Type: Object
Default:

handlebars: {
  partials: null,
  helpers: null, // NOTE: handlebars-layouts are registered by default
}

Passed to gulp-hb.

Partials and helpers are resolved via handlebars-wax. This is happening outside of the task function, allowing us to export the handlebars instance with partials and helpers already registered. It can be required via require('@unic/estatico-handlebars').handlebars.

A simple helper example:

{
  helpers: {
    link: object => `<a href="${object.url}">${object.text}</a>`,
    foo: bar => `<span>${bar}</span>`,
  },
}

If a helpers needs access to handlebars, a factory has to be used instead (see docs on handlebars-wax):

{
  helpers: {
    register: (handlebars) => {
      handlebars.registerHelper('link', (object) => { // eslint-disable-line arrow-body-style
        return new handlebars.SafeString(`<a href="${object.url}">${object.text}</a>`);
      });

      handlebars.registerHelper('foo', bar => `<span>${bar}</span>`);
    },
  },
}

NOTE: handlebars-layouts) is registered by default

plugins.data

Type: Function
Default:

data: (file) => {
  // Find .data.js file with same name
  try {
    const data = require(file.path.replace(path.extname(file.path), '.data.js'));

    return Object.assign({}, data);
  } catch (e) {
    return {};
  }
}

Setting up data to be used in handlebars compiling. Return value will be assigned to file.data where gulp-hb picks it up.

plugins.prettify

Type: Object
Default:

prettify: {
  indent_with_tabs: false,
  max_preserve_newlines: 1,
}

Passed to gulp-prettify. Setting to null will disable this step.

plugins.clone

Type: Object
Default:

clone: dev ? null : {
  data: {
    env: {
      dev: false,
    },
  },
  rename: filePath => filePath.replace(path.extname(filePath), `.prod${path.extname(filePath)}`),
},

This potentially speeds up CI builds (where the same templates are built with both a dev and prod config) since we only run the expensive task of setting up the data once.

The CI needs to take care of moving & renaming the .prod.html files.

logger

Type: { info: Function, debug: Function, error: Function }
Default: Instance of estatico-utils's Logger utility.

Set of logger utility functions used within the task.

env

Type: Object
Default: {}

Result from parsing CLI arguments via minimist, e.g. { dev: true, watch: true }. Some defaults are affected by this, see above.

License

Apache 2.0.

Readme

Keywords

none

Package Sidebar

Install

npm i @unic/estatico-handlebars

Weekly Downloads

67

Version

0.0.11

License

Apache-2.0

Unpacked Size

19.3 kB

Total Files

14

Last publish

Collaborators

  • team-unic
  • backflip
  • oriol.tf
  • rbnlffl
  • lbsonley