handlebars-react icon indicating copy to clipboard operation
handlebars-react copied to clipboard

Installation command not working

Open tonydiaz opened this issue 9 years ago • 15 comments

Getting a 404 error:

npm ERR! Darwin 14.5.0 npm ERR! argv "node" "/usr/local/bin/npm" "install" "handlebars-react" "--save-dev" npm ERR! node v0.12.5 npm ERR! npm v2.11.2 npm ERR! code E404

npm ERR! 404 Registry returned 404 for GET on http://registry.npmjs.org/handlebars-react npm ERR! 404 npm ERR! 404 'handlebars-react' is not in the npm registry. npm ERR! 404 You should bug the author to publish it (or use the name yourself!) npm ERR! 404 It was specified as a dependency of 'nautilus' npm ERR! 404 npm ERR! 404 Note that you can also install from a npm ERR! 404 tarball, folder, http url, or git url.

tonydiaz avatar Sep 10 '15 18:09 tonydiaz

It has not been released yet. It's not useful in its current state anyway as it does not yet compile the parsed handlebars expressions.

stevenvachon avatar Sep 10 '15 18:09 stevenvachon

any word on when this will be ready? could really be useful to the Meteor community to compile spacebars (which is basically just handlebars with a few additions) to JSX.

faceyspacey avatar Dec 02 '15 21:12 faceyspacey

Probably in January. Getting another project to a happy point, then holidays. I want this done too.

stevenvachon avatar Dec 02 '15 22:12 stevenvachon

What needs to be done? How could one contribute? What's the strategy?

faceyspacey avatar Dec 02 '15 22:12 faceyspacey

The bulk of the work is in handlebars-html-parser. The strategy is to write a parser that makes any subsequent compiler extremely easy and non-redundant to write as there will be many similar to this one.

stevenvachon avatar Dec 02 '15 22:12 stevenvachon

what's missing from it?

...I don't suppose you could give me a hint to get started on one of the Roadmap-listed features, eg:

add support for {{#if}},{{else}},{{else if}},{{#unless}}

?

faceyspacey avatar Dec 02 '15 22:12 faceyspacey

I just pushed v0.0.18-preview for you to check out. It contains a lot of cleanup and other stuff that I started a while back but hadn't finished. I haven't worked on this in over a month, so I can't remember much. I do know that I hadn't finished interpolating sub-expressions.

In case you're wondering, I went with patches instead of minor versions because I wanted to communicate that it's not just in beta, but it's unusable.

stevenvachon avatar Dec 02 '15 22:12 stevenvachon

@stevenvachon I've never built a parser. What should I study to be able to work on this? What parsing technique did you implement? I imagine there is a documented strategy you based this on.

faceyspacey avatar Dec 05 '15 13:12 faceyspacey

No particular pre-determined parsing technique -- just went with what would produce an AST that would support as many uses of Handlebars and HTML as possible. In the end, I went with a linear program to avoid excessive nesting. Existing handlebars and html parsers were used -- I didn't want to "reinvent the wheels". Check out the wiki for some details.

stevenvachon avatar Dec 05 '15 18:12 stevenvachon

@stevenvachon I'm assuming the parser is going to have some similar JSX gotchas like className and htmlFor?

Also does it support #each in its current state?

DylanPiercey avatar Dec 05 '15 22:12 DylanPiercey

@DylanPiercey those are already handled. #each is not currently supported.

stevenvachon avatar Dec 05 '15 23:12 stevenvachon

@DylanPiercey @stevenvachon there will be other gotchas too like achieving ../... That requires each component to have a link to its parent so we can traverse the component tree backwards. Contrary to what React purists might think, it won't break React. You just can't use it with the Pure Render mixin.

Basically, the idea is that you have a reference to the parent, and if the parent changes (i.e. is forced to update), well, the reality is you (the child component) are forced to update as well, and therefore receive a reference to the new parent component instance. You won't have a situation where the child component is rendering a stale parent data context, or the child component itself is stale with the data context up to date (the latter would definitely not happen). You could up with stale data if--like the Pure Render mixin--you chose not to update in shouldComponentUpdate. But that's a fair limitation to have if you want full Handlebars syntax--i.e. you're not allowed to use the Pure Render mixin.

...I've been working on similar stuff for transpilation of Meteor's Spacebars, which basically is Handlebars. @timbrandin and I have been approaching this--but struggling--with regexes on the Blaze React project: https://github.com/timbrandin/blaze-react

What I have in our broken regex approach is adding a reference (in the transpilation build step) to the parent in every component created like this:

https://github.com/ultimatejs/helper-lookup/blob/master/jsx-plugin.js#L15

Then in our __lookup() method--which looks up all variables within Spacebars--I traverse the linked list backwards to find parent data context:

https://github.com/ultimatejs/helper-lookup-blaze-react/blob/master/helper-lookup-mixin.js#L31 https://github.com/ultimatejs/helper-lookup-blaze-react/blob/master/helper-lookup-mixin.js#L94

faceyspacey avatar Dec 06 '15 00:12 faceyspacey

@DylanPiercey @stevenvachon as for #each, what I've found is basically we should solve custom block helpers and #each, #with, #if, and #unless as if it's no different. In other words, we should solve custom block helpers and #each with the same solution.

So I made React components for these block helpers:

https://github.com/ultimatejs/helper-lookup-blaze-react/blob/master/handlebars-components.js

For example, this:

{{#each posts}}
    <div>
        <h1>{{title}}</h1>
        <p>{{body}}</p>
    </div>
{{else}}
  <div>sorry, no posts</div>
{{/each}

becomes:

<Each 
    parent={this} data={this.__lookup('posts')} 
    contentBlock={() => <div><h1>{this.__lookup('title')}</h1><p>{this.__lookup('body')}</p></div> } 
    elseBlock={() => <div>sorry, no posts</div> } 
/>

Here's what the Each React component class definition looks like:

Each = React.createClass({
    mixins: [HandlebarsMixin],
    renderFunc() {
        let {data, parent, contentBlock, elseBlock} = this.props;

        if(_.isArray(data) && !_.isEmpty(data)) {
            return data.map((item, index) => {
                return this._contentBlockWithData(contentBlock, parent, item);
            });
        }
        else return elseBlock.call(parent);     //i.e. run in context where block defined
    }
});

Here's the code for all such Handlebars component classes in React:

https://github.com/ultimatejs/helper-lookup-blaze-react/blob/master/handlebars-components.js

and here's the simple Mixin they all use: https://github.com/ultimatejs/helper-lookup-blaze-react/blob/master/handlebars-mixin.js

...Now obviously this is for a crappy regex-replacing-based apprach. But I imagine the same will apply here when it comes to the codegen step of a true parser. In short, by mirroring things like #each and #if we don't even have to generate any/much real javascript. We can just generate JSX-style HTML (with functions [that return more JSX html] occasionally as parameters). This also is how we deal with custom block helpers. There's basically 1-to-1 parity between custom block helpers and React components, so we harness that as much as possible to minimize the work we gotta do.

faceyspacey avatar Dec 06 '15 00:12 faceyspacey

@faceyspacey the idea with this library is not to compile to JSX nor to provide React components that re-implement Handlebars, but to instead depend on the Handlebars runtime (~14kb minified). Maintenance of Handlebars logic is offloaded this way.

stevenvachon avatar Dec 11 '15 15:12 stevenvachon

@faceyspacey did you ever get this working?

soundyogi avatar Oct 19 '18 22:10 soundyogi