shannonmoeller / gulp-hb

A sane Gulp plugin to compile Handlebars templates. Useful as a static site generator.
http://npm.im/gulp-hb
MIT License
147 stars 14 forks source link

Issue loading in handlebars-layouts #31

Closed spacedawwwg closed 8 years ago

spacedawwwg commented 8 years ago

I'm trying to combine gulp-hb and handlebars-layouts

It seems in v2, handlebars-layouts was somehow bundled in and simply worked without the need to load it in as a helper.

My guessing, since the upgrade to v3, handlebars-layouts isn't working this way and needs to be registered with the gulp-hb version of handlebars.

I'm just wondering what the best way to register this is, the example below does not seem to work.

Thanks for any help in advance.

"use strict";
var gulp = require('gulp');
var plumber = require('gulp-plumber');
var frontMatter = require('gulp-front-matter');
var extname = require('gulp-extname');
var hb = require('gulp-hb');
var hbLayouts = require('handlebars-layouts');
// register layout helpers
hbLayouts.register(hb.handlebars);

var config = require('../config');
var handleError = require('../misc/handleError');

gulp.task('markup--compile', function () {
   return gulp.src(config.inputFiles.pages)
    .pipe(plumber({
      errorHandler: handleError
    }))
    .pipe(frontMatter({
      property: 'front',
      remove: true
    }))
    .pipe(extname())
    .pipe(hb({
      data: config.inputFiles.data,
      partials: config.inputFiles.templates,
      helpers: config.inputFiles.helpers,
      bustCache: true
    }))
    .pipe(gulp.dest(config.basePaths.dist));
});

currently getting

{ [Error: Missing helper: "extend"]
  description: undefined,
shannonmoeller commented 8 years ago

This is one of the v3 breaking changes. The every time hb() is run, it will get a new instance of handlebars. This solved issues #24 and #29.

The solution is to leverage another of the breaking changes. Specifically, the ability to register things in separate groupings using the fluent API. Give this a try:

"use strict";
var gulp = require('gulp');
var plumber = require('gulp-plumber');
var frontMatter = require('gulp-front-matter');
var extname = require('gulp-extname');
var hb = require('gulp-hb');

var config = require('../config');
var handleError = require('../misc/handleError');

gulp.task('markup--compile', function () {
   return gulp.src(config.inputFiles.pages)
    .pipe(plumber({
      errorHandler: handleError
    }))
    .pipe(frontMatter({
      property: 'front',
      remove: true
    }))
    .pipe(extname())
    .pipe(hb()
      .data(config.inputFiles.data)
      .partials(config.inputFiles.templates)
      .helpers(config.inputFiles.helpers)
      .helpers('../node_modules/handlebars-layouts/index.js')
    )
    .pipe(gulp.dest(config.basePaths.dist));
});

The new API allows you to call .helpers() multiple times, where each call can have it's own globs and options.

This use case gives me an idea for an additional feature to make the whole ../node_modules... bit cleaner by accepting .helpers(require('handlebars-layouts')). Working on it!

spacedawwwg commented 8 years ago

Thanks, this has fixed the missing helper issue!

...BUT (I'm really sorry @shannonmoeller !!), I'm now getting [Error: Missing partial: 'layouts/layout--master'] errors.

My partials are simply "src/templates/**/*.hbs"

shannonmoeller commented 8 years ago

Is "src/templates/*/.hbs" a typo? Would expect "src/templates/**/*.hbs".

spacedawwwg commented 8 years ago

You are correct * Blushes *

shannonmoeller commented 8 years ago

No worries!

Ok. If you update to the just-released v3.1.0, you should be able to do this:

.helpers(require('handlebars-layouts'))
thezimmee commented 8 years ago

Hello. It's been a while since I used this (love it by the way), but I just updated to the latest version and am running into the same error message referenced above:

Missing helper: "extend"

I think I'm following your examples correctly... and I started a clean gulpfile.js with only the necessary code but it's not working for me. I hope it's not a silly little oversight on my part, but if you could help me out I'd appreciate it. Here is my gulpfile.js:

/** Grab modules */
var gulp = require('gulp');
var hb = require('gulp-hb');

/**
 * Handlebars compilation
**/
gulp.task('hbs', function () {
    return gulp
        .src('./src/**/*.html.hbs')
        .pipe(hb()
            .data('./data/**/*.json')
            .partials('./src/components/**/*.hbs')
            .partials('./src/layouts/**/*.hbs')
            .helpers(require('handlebars-layouts'))
        )
        .pipe(gulp.dest('./build'));
});

My package.json only has a few dependencies:

"devDependencies": {
    "gulp": "github:gulpjs/gulp#4.0",
    "gulp-hb": "^3.1.2",
    "gulp-load-plugins": "^1.2.0",
    "handlebars-layouts": "^3.1.3"
  },

Thank you much!

shannonmoeller commented 8 years ago

At first glance that looks like it should work. I'll setup a test case and dig a little deeper.

shannonmoeller commented 8 years ago

@thezimmee This turned out to be an issue with handlebars-wax. That has been resolved and published, so I updated the deps here and released as v3.2.0.

thezimmee commented 8 years ago

Awesome. I will test tomorrow to confirm. Thank you!

spacedawwwg commented 8 years ago

I'm still having a lot of issues with v3.x

I still get the Missing partial issue no matter what I change my paths to and the Missing helper issue when I try

.helpers(require('handlebars-layouts'))`

I find it confusing, as I haven't changed anything from the previous version other than registering things in separate groupings (as per your example above)

I'm going to stick with v2 for my current projects until I've had chance to experiment.

shannonmoeller commented 8 years ago

@spacedawwwg As I've been testing more I've run into similar issues. It seems to be related to how Handlebars implements the require.extensions hook for loading .handlebars and .hbs files.

shannonmoeller commented 8 years ago

All of the helpers and partials are now registered properly, but when attempting to use a partial that was compiled with the global instance of Handlebars (as is the case with that require hook), it fails to locate registered helpers.

Sorry for the back and forth on this. Thanks for sticking with me.

shannonmoeller commented 8 years ago

@spacedawwwg @thezimmee The require.extensions issue is resolved. I've updated my personal site as an end-to-end test case using partials and handlebars-layouts and it's working as expected. Released as v3.2.1. Thank you, both.

https://github.com/shannonmoeller/shannonmoeller.com/blob/develop/gulpfile.js#L25

thezimmee commented 8 years ago

@shannonmoeller, sorry for the delay, but I just did a quick check and confirmed it works for me. Thanks for your help with this!!!

spacedawwwg commented 8 years ago

Im still unable to get v3 working.

gulpfile.js

var requireDir = require('require-dir');

// recursively define gulp tasks
requireDir('build', {
  recurse: true
});

build/config.js

var basePaths = {
  src: 'src/',
  dist: 'dist/'
};

var inputFiles = {
  pages: basePaths.src + 'pages/**/*.hbs',
  data: basePaths.src + 'data/**/*.{json,yml}',
  templates: basePaths.src + 'templates/**/*.hbs',
  helpers: basePaths.src + 'helpers/*.js'
};

build/markup/markup--compile.js

"use strict";
var gulp = require('gulp');
var plumber = require('gulp-plumber');
var extname = require('gulp-extname');
var hb = require('gulp-hb');
var hbLayouts = require('handlebars-layouts');

var config = require('../config');
var handleError = require('../misc/handleError');

gulp.task('markup--compile', function () {
   return gulp.src(config.inputFiles.pages)
    .pipe(plumber({
      errorHandler: handleError
    }))
    .pipe(extname())
    .pipe(hb()
      .data(config.inputFiles.data)
      .partials(config.inputFiles.templates)
      .helpers(config.inputFiles.helpers)
      .helpers(hbLayouts)
    )
    .pipe(gulp.dest(config.basePaths.dist));
});

src/pages/01_landing.hbs

{{#extend "layouts/layout--master"}}
  {{#content "master__body"}}
    {{> components/hero}}
    {{> components/section--standout}}
    {{> components/section--improve}}
    {{> components/section--exams}}
    {{> components/section--testimonials}}
    {{> components/section--experts}}
    {{> components/section--video}}
    {{> components/section--support}}
    {{> components/section--contact}}
    {{> components/modal--signup}}
  {{/content}}
{{/extend}}

error screen shot 2016-02-18 at 11 30 28

file structure screen shot 2016-02-18 at 11 31 03

shannonmoeller commented 8 years ago

@spacedawwwg Try setting cwd:

hb({ cwd: process.cwd() })
spacedawwwg commented 8 years ago

Thats was it, @shannonmoeller!

dancingdrunk_ron

shannonmoeller commented 8 years ago

@spacedawwwg The underlying lib handlebars-wax is using __dirname as a default instead of process.cwd(). I think it would make sense for gulp-hb to default back to process.cwd() as that's how gulp.src works. Thoughts?

spacedawwwg commented 8 years ago

I don't think handlebars-wax should change at all.

But I do think, as this is a gulp plugin, changing the default in gulp-hb to follow the same pattern as gulp's defaults (i.egulp.src), for simplicities sake and ease of integration, would probably be more beneficial to developers like myself.

Though, its not a massive task to add this setting now I know about it (so maybe a note in the README may suffice?)

shannonmoeller commented 8 years ago

It's an easy change to make gulp-hb use cwd() without having to change the underlying libs and I like the consistency it would bring. I'm going to make that change and release v4. Thanks again for all your help bug squashing v3.

shannonmoeller commented 8 years ago

v4 released.

@spacedawwwg @thezimmee This thread is getting pretty long, so I'm going to lock it down. I'll gladly help solve any other issues you may encounter, but would ask that they be reported in a new issue. Thanks!