Closed shannonmoeller closed 9 years ago
@waynedpj If I'm not mistaken, it appears that the issue is that I call handlebars.registerHelper(helpers);
directly, correct?
i am no expert but i believe that is the issue, along with returning the helpers
object instead of the passed in Handlbars instance.
since Assemble just needs an object of helpers, simply returning the helpers
as the default export should suffice. and it makes your lib more flexible IMHO in case users want to register your helpers under different names with Handlebars (e.g. to avoid name conflicts among helpers).
obviously you could still export a separate register
method for backwards compatibility with old Assemble/etc, or as a utility module, though this all would prob require a breaking version change.
i hope that helps, though you might want to wait for the experts @doowb and @jonschlinkert
everything @waynedpj said is right on. I can't think of anything I would add or change. @doowb?
The problem with returning an object of helpers is that I need a reference to the handlebars partials array. I see a number of the github.com/helper repos have functions that accept an engine
param and return a helper function. Any way I can make use of that?
actually I just remembered... engine-assemble is the default engine used by assemble (it's just a wrapper around engine-handlebars that adds some assemble defaults).
engine-handlebars exposes handlebars, so I believe users should be able to do something like this:
var assemble = require('assemble');
var engine = require('engine-assemble');
var layouts = require('handlebars-layouts');
layouts(engine.Handlebars);
(edited to update the H
in handlebars)
@shannonmoeller / @waynedpj let us know if you have ideas for how we can make this kind of thing easier. assemble v0.6.0 follows conventions similar to express/consolidate for engines/helpers - the goal is to provide a good user experience so if we can make this easier I'm all for it
here we go.. this works as-is:
var engine = require('engine-assemble');
var layouts = require('handlebars-layouts');
layouts(engine.Handlebars);
var assemble = require('assemble');
assemble.engine('hbs', engine);
assemble.helpers(engine.Handlebars.helpers);
console.log(assemble)
in case it helpers, this is the [assemble object] with the helpers registered (https://gist.github.com/jonschlinkert/b64fa482c14f07407543#file-assemble-object-js-L54-L57)
I think we still need to fix the issue with engine-cache
to expose engine.Handlebars
properly.
I was thinking about this issue earlier, and if you want to make sure to support native Handlebars along with any of the advanced features in assemble 0.6.0, I think that some of the common functionality can be functions work with either handlebars or assemble...
extend: function (name, options) {
if (this.app) {
return assembleHelpers.extend(this, name, options);
}
return handlebarsHelpers.extend(name, options);
}
and in the main layouts
function it could just be something like:
function layouts(handlebars) {
if (typeof handlebars === 'undefined') {
return helpers;
}
handlebars.registerHelper(helpers);
return handlebars;
};
Then in assemble, we can just load them like:
var assemble = require('assemble');
var layouts = require('handlebars-layouts');
assemble.helpers(layouts());
These are just some quick thoughts.
@doowb My primary issue here is that I need a reference to handlebars.partials
and handlebars.compile
inside the helpers themselves.
https://github.com/shannonmoeller/handlebars-layouts/blob/master/index.js#L101 https://github.com/shannonmoeller/handlebars-layouts/blob/master/index.js#L113
If it weren't for that, I'd totally be on board with just returning an object and calling it a day. Calling registerHelper
in my exported function is just a convenience thing.
@jonschlinkert This problem exists for consolidate as well. Their recommended solution involves providing your own handlebars instance, which isn't exactly user friendly.
https://www.npmjs.com/package/consolidate#template-engine-instances
For handlebars we're talking something along these lines:
var express = require('express'),
consolidate = require('consolidate'),
handlebars = require('handlebars');
consolidate.requires.handlebars = handlebars;
handlebars.registerHelper(...);
express()
.set('view engine', 'hbs')
.engine('hbs', consolidate.handlebars)
...
@jonschlinkert How is this supported by 0.6?
https://github.com/helpers/handlebars-helper-partial/blob/master/index.js#L12-15
Maybe instead of returning handlebars
you can just return the helpers object and that can be used with assemble like:
assemble.helpers(layouts(engine.Handlebars));
The partials helper would be used like this:
var partial = require('handlebars-helper-partial');
assemble.helper('partial', partial(engine.Handlebars));
Works for me if that's the official pattern.
@jonschlinkert How is this supported by 0.6?
I think I made that project to help someone who had a question, probably for assemble 0.4.x. see https://github.com/helpers/handlebars-helper-partial#handlebars-example.
@jonschlinkert How would you solve it differently for 0.6, if at all?
The develop branch has been updated to return the helper object. Calling registerHelper
internally has been moved to the .register
method. It will be released as soon as I have time to update the documentation.
https://github.com/shannonmoeller/handlebars-layouts/blob/develop/index.js#L193,L210
Released as 2.0.
Sorry, so my understanding here is:
var assemble = require('assemble');
var layouts = require('handlebars-layouts');
assemble.helper(layouts(engine.Handlebars));
..is the correct way to register handlebars-layouts for assemble 0.6.x now?
UPDATE: This is obviously not the solution :) Could we get an example?
@spacedawwwg Give this a shot.
var assemble = require('assemble');
var engine = require('engine-assemble');
var layouts = require('handlebars-layouts');
assemble.engine('hbs', engine);
assemble.helpers(layouts(engine.Handlebars));
Do I need to include 'engine-assemble' as a devDependancy (thought i would be available through assemble)
I'm getting this error:
module.js:338
throw err;
^
Error: Cannot find module 'engine-assemble'
at Function.Module._resolveFilename (module.js:336:15)
at Function.Module._load (module.js:278:25)
at Module.require (module.js:365:17)
at require (module.js:384:17)
at Object.<anonymous> (/Users/Paul/Sites/PROJECT/html/gulpfile.js:27:14)
at Module._compile (module.js:460:26)
at Object.Module._extensions..js (module.js:478:10)
at Module.load (module.js:355:32)
at Function.Module._load (module.js:310:12)
at Module.require (module.js:365:17)
at require (module.js:384:17)
It's a dependency of a dependency, so if you want to use this pattern, yes, you'll need to:
npm i -D engine-assemble
Got it! Many thanks, dude
Unfortunately, while assemble 'builds', the output of the 'layout' is empty using:
var assemble = require('assemble');
var engine = require('engine-assemble');
var helpers = {
layouts: require('handlebars-layouts'),
repeat: require('handlebars-helper-repeat')
};
// Register Helpers
assemble.engine('hbs', engine);
assemble.helper('repeat', helpers.repeat);
assemble.helper(helpers.layouts(engine.Handlebars));
for now, to keep thiis working, I am using:
var assemble = require('assemble');
var handlebars = require('handlebars');
var helpers = {
layouts: require('handlebars-layouts'),
repeat: require('handlebars-helper-repeat')
};
// Register Helpers
handlebars.registerHelper('repeat', helpers.repeat);
handlebars.registerHelper(helpers.layouts(handlebars));
hopefully I can figure out how to use Assemble handlebars engine, but as I say this is working for now.
@spacedawwwg Layouts returns an object which you register with the plural method .helpers()
:
assemble.helper('repeat', helpers.repeat);
assemble.helpers(helpers.layouts(engine.Handlebars));
Still no luck with that I wonder if @doowb or @jonschlinkert could way in on this?
Sorry for no follow up! @doowb and I are both working against (different) deadlines. One of use will try to review more asap. I hate the idea of having people do workarounds, we'll try to come up with a solution
This thread is deviating from the original closed issue. Because, at its core, this is really an issue with the template.helper
method, I've started a new thread there:
jonschlinkert/template#25
After several unsuccessful attempts, I decided to check what handlers-layouts
package does.
Few more attempets and I got working solution :dancer:
import gulp from 'gulp';
import assemble from 'assemble';
import engineAssemble from 'assemble/node_modules/engine-assemble';
import handlebarsLayouts from 'handlebars-layouts';
import gulpLoadPlugins from 'gulp-load-plugins';
const $ = gulpLoadPlugins();
// Doesn't work
//assemble.engine('hbs', engineAssemble);
//assemble.helpers(handlebarsLayouts(engineAssemble.Handlebars));
// Doesn't work
//assemble.helpers(handlebarsLayouts(engineAssemble.Handlebars));
// This one is weird...
// It should work but it doesn't...
// Probably assemble.helpers does something behind the scenes
//assemble.helpers(handlebarsLayouts.register(engineAssemble.Handlebars));
// It works!
//engineAssemble.Handlebars.registerHelper(handlebarsLayouts(engineAssemble.Handlebars));
// It works too!
handlebarsLayouts.register(engineAssemble.Handlebars);
assemble.partials(['app/views/partials/*.hbs']);
assemble.layouts(['app/views/layouts/*.hbs']);
gulp.task('assemble', () => {
return gulp.src(['./app/views/pages/*.hbs'])
.pipe($.assemble(assemble))
.pipe($.extname())
.pipe(gulp.dest('dist'));
Hey guys,
I'm using assembly 0.6.0-beta.5
and handlebars-layouts 3.1.2
with small help of gulp-assemble
.
After few hours of fighting, I ended with this:
import gulp from 'gulp';
import assemble from 'assemble';
import engineAssemble from 'engine-assemble';
import handlebarsLayouts from 'handlebars-layouts';
import config from './../config.js';
// Configure assemble
assemble.engine('hbs', engineAssemble);
assemble.helpers(handlebarsLayouts(engineAssemble.Handlebars));
assemble.partials(['app/views/partials/*.hbs', 'app/views/layouts/*.hbs']);
assemble.layouts(['app/views/layouts/*.hbs']);
assemble.option({
assets: (config.dev) ? 'dev/assets' : 'dist/assets',
layout: false
});
gulp.task('assemble', () => {
return gulp.src(['./app/views/pages/*.hbs'])
.pipe($.assemble(assemble))
.pipe($.extname())
.pipe($.if(config.dev, gulp.dest('dev'), gulp.dest('dist')));
});
It takes layout and renders it but {{#block}}
are not replaced with {{#content}}
, partials don't work anymore.
layout-main.hbs
<!doctype html>
<html class="no-js" lang="en">
<head>
<body>
{{#block "body"}}
{{/block}}
</body>
</html>
index.hbs
{{#extend "layout-main"}}
{{#content "body"}}
Test body
{{/content}}
{{/extend}}
Renders to:
index.html
<!doctype html>
<html class="no-js" lang="en">
<head>
<body>
</body>
</html>
I have the same problem. the block won't be replaced by content. Is there any fix?
@hinok @StephanGerbeth
Assemble does it's own layout magic. Have you tried registering your layouts as plain partials?
// change this
assemble.layouts(['app/views/layouts/*.hbs']);
// to this
assemble.partials(['app/views/layouts/*.hbs']);
Actually, it looks like you are already registering them as partials, so you could just drop the .layouts()
line altogether.
yeah I think @shannonmoeller's suggestion seems like the right solution.
@shannonmoeller sorry looks like I missed some of the later comments here. we're finally working on docs - we'll be sure to update those to mention this lib when we get to that part. I'll go look at that template helper issue again...
@jonschlinkert Thanks!
Ok i try to explain my problem more detailed.
Here is my actual implementation/configuration of assemble@0.6.0-beta.5 (short version)
When i try to use {{#content "xyz"}}
and {{#block "xyz"}}
the block tag won't be replaced by content tag e.g.
index.hbs
<div>
{{#extend "elements/content"}}
{{#content "xyz"}}
<p>NEW CONTENT</p>
{{/content}}
{{/extend}}
</div>
partials/elements/content.hbs
<div class="content">
{{#block "xyz"}}
<p>REPLACE CONTENT</p>
{{/block}}
</div>
Result
<div>
<div class="content">
<p>REPLACE CONTENT</p>
</div>
</div>
Expected Result
<div>
<div class="content">
<p>NEW CONTENT</p>
</div>
</div>
Can you help me, please?
Cheers Stephan
ok my fault.
I used assemble.helpers(layouts(engine.Handlebars));
to load the handlebars-layouts helper. But the right one is engine.Handlebars.registerHelper(layouts(engine.Handlebars));
to register them.
Now it is working well. I hope so ;)
Cheers Stephan
@StephanGerbeth I'm glad you got it working! That said, I'll dig in to see why assemble.helpers
doesn't work as that's something I'll want to support.
I also updated this issue with the actual/corrected code of my implementation. Perhaps i will post a link to my boilerplate in the near future which builds on assemble-, postcss- and webpack-package, with a small documentation helper :)
I've been hacking with code and found temp solution... (not the best but works).
handlebarsLayouts.register(engineAssemble.Handlebars);
function embed() {
handlebarsLayouts.register(engineAssemble.Handlebars);
return engineAssemble.Handlebars.helpers.embed.apply(this.context, arguments);
}
assemble.helper('embed', embed);
I've found that assemble
uses engine-assemble
which uses handlebars-helpers
which has defined helper called embed
.
embed
from handlebars-layouts is overriden by new embed
from handlebars-helpers.
When I use {{#embed}} from handlebars-layouts
, page.hbs is correctly rendered!
Still it's a bit weird that on old stack npm, node - I could put {{#extend}}
inside {{#extend}}
.
Probably related to https://github.com/shannonmoeller/handlebars-layouts/issues/19
I updated today my stack to newest packages:
node 5.1.0
npm 3.4.1
handlebars-layouts 3.1.3
assemble 0.6.0-beta.5
gulp-assemble 0.3.2
I had one small issue with engine-assemble
which is placed now directly in node_modules/
. It was easy to fix.
It seems that everything works but I found one small problem. In my project I used construction like this:
page.hbs
{{#extend "layout-main"}}
{{#content "body"}}
{{#extend "header"}}
{{#content "header-bottom"}}
<p>Some text</p>
{{/content}}
{{/extend}}
{{/content}}
{{/extend}}
layout-main.hbs
<html>
<body>
{{#block "body"}}
{{/block}}
</body>
</html>
header.hbs
<h1>Header</h1>
{{#block "header-bottom"}}
{{/block}}
Expected result of page.hbs -> page.html
<html>
<body>
<h1>Header</h1>
<p>Some text</p>
</body>
</html>
Current result of page.hbs -> page.html
<html>
<body>
<h1>Header</h1>
<!-- missing paragraph... -->
</body>
</html>
It's a bit weird because it works without any problems on node 0.12 and npm 2+.
assemble/assemble#682
Assemble 0.6.0 drops the
register
pattern, so an alternative pattern needs to be implemented forhandlebars-layouts
to work seamlessly.For reference: https://github.com/helpers/helper-front-matter/blob/master/index.js