Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What is the purpose of mustache.js? #406

Closed
phillipj opened this issue Dec 17, 2014 · 22 comments
Closed

What is the purpose of mustache.js? #406

phillipj opened this issue Dec 17, 2014 · 22 comments

Comments

@phillipj
Copy link
Collaborator

Hi!

I've been trying to help by reviewing pull requests lately and has seen alot of feature requests. Many of these features are not part of the mustache spec, but would clearly be nice to have in many scenarios. It would be of great value if I knew more about the purpose of this project when reviewing and cleaning up these pull requests.

Should it be strictly mustache spec compliant (and nothing more)? Or are some nice to have features allowed?

Answering those two questions in the readme with help alot both for contributers and reviewers.

@dasilvacontin
Copy link
Collaborator

I couldn't agree more.

When I read the README.md I get the feeling that, currently, mustache.js is spec compliant and nothing more. Otherwise, if it had deviations regarding the spec, it would be nice to have them listed there.

IMO, it wouldn't be such bad idea to add helpful features on top of mustache.js, as long as mustache.js remains spec compliant. On the other hand, there's also the beauty of leaving it as a direct compliant port. But I prefer usefulness over beauty in this case.

It would be great to hear @janl's opinion on this.

@janl
Copy link
Owner

janl commented Dec 17, 2014

I don’t think having a moustache spec + extra features in the project.

At one time I also tried to introduce some sort of plugins, so extra features can be opted into.

One big purpose of mustache in general is that templates can be shared among implementations (Ruby in the backend, JS in the frontend e.g.). This premise should never break. If you happen to use Node.js in the back, then you could opt into extra features only provided by mustache.js.

Extra features and their popularity should also affect the development in the spec, much like browsers vendors and the w3c/whatwg :)

Does this help? :)

@phillipj
Copy link
Collaborator Author

Absolutely! It should be much easier to clean up old and stale pull requests with that in mind.

Couldnt agree more with building an extensible core module with plugins and/or hooks, rather than adding possibly handy features into the core.

@bobthecow
Copy link

Mustache.php ships a couple of common extensions to the spec using pragma tags:

https://github.com/bobthecow/mustache.php/wiki/Pragmas

There's precedent for this. That is how dot notation and implicit iterators were implemented in the ruby version before spec v1.

@dasilvacontin
Copy link
Collaborator

I don't know how I could miss the point of interoperable templates, sorry for that. But indeed, extending the features in some way would be handy, and it's also a way to show the spec maintainers what users really want. (and let those inpatient/uncomfortable users customise at will)

@bobthecow, how is the state of including the FILTER and BLOCK pragmas into the spec?

@dgmike
Copy link

dgmike commented Dec 17, 2014

👀 great discussion.

@bobthecow
Copy link

They won't be included until v2, if they are at all. That said, there's a decent amount of support for both — hogan.js, mustache.java, Mustache.php and GRMustache all implement the proposed BLOCKS syntax, and they're all compatible. I believe they're enabled by default in all of 'em besides Mustache.php, which requires either a flag on the engine or a {{% BLOCKS }} pragma tag in your template to work.

See mustache/spec#75 for discussion on that.

@dasilvacontin
Copy link
Collaborator

Awesome, thanks for the info and the pointers @bobthecow! It would be awesome to bring those pragmas to mustache.js, specially the BLOCKS one.

Also, I've seen over http://satchmorun.github.io/mote/ that we are quite slow compared to other mustache-compliant js libraries; maybe we could look into improving that. :)

Refactoring some functions would make the codebase easier to maintain, understand and extend. I'm specially looking at parseTemplate (~125 lines) and Writer.prototype.renderTokens (~100 lines).

@groue
Copy link

groue commented Dec 18, 2014

@janl wrote:

One big purpose of mustache in general is that templates can be shared among implementations (Ruby in the backend, JS in the frontend e.g.). This premise should never break.

This premise should be taken with a pinch of salt. It has always been weak, right from the beginning, for the simple reason that "falsey" and "truthy" are specifed as language-dependent. There is no guarantee that {{# test }}...{{/ test }} will render the same for the same input. Of course 0 (zero) is at the center of the problem. There is some evidence that the empty string is another.

Given this fuzziness, and the stalled evolution of the spec (three years without a commit), GRMustache has taken another take. The 6th most-starred Mustache implementation on github (after 3 javascript implementations, the Ruby one and the PHP one) is spec-compliant and at the same time provides a bunch of extra features that address frequent use cases found in issues or Stack Overflow. The documentation has a clear compatibility paragraph for each of those extra features, at the place where they are documented. There is also a dedicated page which lists all the library extensions: https://github.com/groue/GRMustache/blob/master/Guides/compatibility.md.

@dasilvacontin
Copy link
Collaborator

I don't understand why the "falsey" and "truthy" workings were left to be language-dependent. What is the purpose of having a spec for how should mustache implementations work, if you don't assure template sharing after all?

I didn't know mustache was in such a bad state, to be honest. Thanks for insight @groue, it's really helpful.

One at this point would even consider forking the spec.. 😅

@groue
Copy link

groue commented Dec 18, 2014

This is history, now.

@dasilvacontin
Copy link
Collaborator

If we want to achieve true interoperable templates we either try pushing/updating the current spec, or we fork the spec to achieve the vision. I think most of us want interoperable templates. I thought they already were, until today.

I read that one of the justifications for this language-implementation discrepancies was so that the user wouldn't need to check the spec/docs so often, or run into counter-intuitive scenarios (eg truthy value on the language is considered as falsy by mustache). Any thoughts on this?

@bobthecow
Copy link

They're effectively interoperable, and I think deferring to the language for truthy/falsey makes sense anyway. There are always going to be things that make sense in one language or implementation that don't map well to others. Like the way an implementation decides whether a value is a lambda or not. Totally different in PHP vs JavaScript vs Ruby vs Objective-C, and that's okay. Because that particular aspect of the spec is an implementation detail. IMO, same with falsey. If you want something to be false, make it false, and there's no ambiguity.

@groue
Copy link

groue commented Dec 18, 2014

I do not agree with @bobthecow. I think the spec should improve its cross-platform compatibility, and clearly state the expected output from various inputs in the JSON format or some widely-used format like JSON, which can handle scalar values such as numbers, booleans, strings, and null/nil/None, plus arrays, and dictionaries. The basic data vocabulary. The spec should enforce the boolean behavior of all values, with explicit tests for ambiguous values such as zero, as well as empty strings. The spec should enforce the condition for walking up the context stack, with explicit tests for disambiguation between missing values vs. explicit nil/null/None values in an object ({{missing_key}} vs. {{existing_key_whose_value_is_nil}}).

As a guy who has used cross-language templates, for both Obj-C and java, so that an iOS and an Android app would share the same templates, I know that It is paramount that cross-language compatibility would be improved. At the cost of begin weird in some language, of course.

Like the way an implementation decides whether a value is a lambda or not.

Yes. A Mustache lambda is a function, whatever the language. It is the job of implementations to provide an API for defining such a spec-compliant function. Mustache does not care about the lambda implementation details.

In the same vein, Mustache cares a lot about a few abstract data types: bools, strings, arrays, dictionaries, and lambdas. Perhaps numbers would enter the list if 0 should be given a special boolean role. The implementation details are left to the implementors. They are not Mustache's business, as long as an empty string (whatever the implementation) is falsey, a dictionary (whatever the implementation) is truthy and can be asked for a key, etc etc (insert the full spec here).

@mjackson
Copy link
Contributor

It's confusing for JS devs to use the spec's definition of falsy instead of JS's. That's why we took the route we did. IMO language independence of templates sounds nice in theory, but doesn't really get you a whole lot in practice. I have yet to use one of my templates in two different languages.

@bobthecow
Copy link

I have used templates in multiple languages. The one thing I've never done is used raw data in multiple languages. That, IMO, is the bigger problem (and the biggest problem with Mustache). People come into it with the assumption, based on past templating language experience, that they can just dump data into their templates and deal with everything there. That's fine for some templating languages, but doesn't work so well when you get into "logic-less" or "less logic". They'd be much better served using a real data model (Presenter, ViewModel, whatever you want to call it), written in the host language, which handled all these sorts of issues for them.

@janl
Copy link
Owner

janl commented Dec 18, 2014

@mjackson I wouldn’t discount the multi-platform argument just because you don’t have a use for it, but I agree with @bobthecow and the basic sentiment: mustache.js should inherit the falsy definition of JS, if you need cross platform falsieness, use explicit false.

@groue
Copy link

groue commented Dec 18, 2014

Let's be practical. Far reaching consequences of such a decision is, for example, that the common use case "How can I render a section if and only if a collection is not empty?" either requires an extra-key (the presenter way), or sends you into a deep hole of compatibility issues (not everyone wants to build a presenter each time one has to render a complex graph of objects). See https://github.com/groue/GRMustache/blob/master/Guides/runtime.md#rendering-a-section-once-when-a-collection-contains-several-items

@janl
Copy link
Owner

janl commented Dec 18, 2014

an option for this would be a "strict" mode (think "use strict";), but I wouldn’t make this a priority.

@bobthecow
Copy link

{{% STRICT }}

@bobthecow
Copy link

I'm a huge fan of pragmas for things like this, because they're falsey if an implementation doesn't support them, or doesn't know that pragma :)

@phillipj
Copy link
Collaborator Author

Thanks alot for great tips and discussions on this topic! I didnt know about the pragmas concept, seems like a good idea for non-spec features. Pragmas being a cross-cutting concept amongst other mustache projects should make it an even more attractive pattern.

@phillipj phillipj mentioned this issue Jan 6, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants