Hi Everyone, I wanted to share my initial thoughts after reading the docs for the proposed Boost.Mustache. If some library docs said "I am implementing JSON", I more-less know what to expect, because JSON is popular, I used it, so one can reliably predict what the library delivers. This is not the case with Mustache. It is the first time I have heard this name. Apparently, it is a less popular thing. Therefore, I would expect some more introduction than just an external link. The linked page also doesn't contain sufficient information but further links. For instance to https://mustache.github.io/mustache.5.html, but this information also doesn't help me find answers to my questions: 1. What is considered an "optional part" of mustache? Boost.Mustache says it only implements the non-optional parts, but docs in mustache(5) do not indicate the optional parts. 2. It is clear to me that the procedure takes a template (with mustaches) and the data to be replaced. But what is the range of the acceptable formats of this data? The examples show that it is JSON, but does it have to be JSON? Boost.Mustache docs say it could be 'described' classes? But is that all? How about Boost.PropertyTree? What does the specification for Mustache say about it? 3. I do not see any specification (neither in Boost.Mustache docc, nor in the linked mustache(5)) for what is the required behavior when I have nested mustashes with the same name, or a JSON file with nested elements of the same name. Or did I miss this description? Regards, &rzej;
Andrzej Krzemienski wrote:
Hi Everyone,
I wanted to share my initial thoughts after reading the docs for the proposed Boost.Mustache.
If some library docs said "I am implementing JSON", I more-less know what to expect, because JSON is popular, I used it, so one can reliably predict what the library delivers.
This is not the case with Mustache. It is the first time I have heard this name. Apparently, it is a less popular thing. Therefore, I would expect some more introduction than just an external link.
You are right, the MVP in this case turned out to be too M. I should add a documentation section that describes the Mustache syntax.
The linked page also doesn't contain sufficient information but further links. For instance to https://mustache.github.io/mustache.5.html, but this information also doesn't help me find answers to my questions:
1. What is considered an "optional part" of mustache? Boost.Mustache says it only implements the non-optional parts, but docs in mustache(5) do not indicate the optional parts.
These are described here: https://github.com/mustache/spec
2. It is clear to me that the procedure takes a template (with mustaches) and the data to be replaced. But what is the range of the acceptable formats of this data? The examples show that it is JSON, but does it have to be JSON? Boost.Mustache docs say it could be 'described' classes? But is that all? How about Boost.PropertyTree? What does the specification for Mustache say about it?
At the moment the supported data sources are json::value and types convertible to json::value via json::value_from. What these types are is explained here: https://www.boost.org/doc/libs/1_81_0/libs/json/doc/html/json/conversion.htm...
3. I do not see any specification (neither in Boost.Mustache docc, nor in the linked mustache(5)) for what is the required behavior when I have nested mustashes with the same name, or a JSON file with nested elements of the same name.
I'm not sure I understand this question. Do you mean things like {{#foo}} {{#foo}} {{foo}} {{/foo}} {{/foo}} ? If so, the way this works is that every element of data["foo"] is pushed to the top of the so-called "context stack", where entities are looked up. If this element itself contains a member "foo", this member will be used for the nested {{#foo}}. (If not, the parent "foo" will be used.)
wt., 7 lut 2023 o 16:00 Peter Dimov via Boost
Hi Everyone,
I wanted to share my initial thoughts after reading the docs for the
Boost.Mustache.
If some library docs said "I am implementing JSON", I more-less know what to expect, because JSON is popular, I used it, so one can reliably predict what the library delivers.
This is not the case with Mustache. It is the first time I have heard
Andrzej Krzemienski wrote: proposed this name.
Apparently, it is a less popular thing. Therefore, I would expect some more introduction than just an external link.
You are right, the MVP in this case turned out to be too M. I should add a documentation section that describes the Mustache syntax.
The linked page also doesn't contain sufficient information but further links. For instance to https://mustache.github.io/mustache.5.html, but this information also doesn't help me find answers to my questions:
1. What is considered an "optional part" of mustache? Boost.Mustache says it only implements the non-optional parts, but docs in mustache(5) do not indicate the optional parts.
These are described here: https://github.com/mustache/spec
Thanks.
2. It is clear to me that the procedure takes a template (with mustaches) and the data to be replaced. But what is the range of the acceptable formats of this data? The examples show that it is JSON, but does it have to be JSON? Boost.Mustache docs say it could be 'described' classes? But is that all? How about Boost.PropertyTree? What does the specification for Mustache say about it?
At the moment the supported data sources are json::value and types convertible to json::value via json::value_from. What these types are is explained here:
https://www.boost.org/doc/libs/1_81_0/libs/json/doc/html/json/conversion.htm...
Ok, so this explains what Boost.Mustache does today. But on a higher level, does the *specification* for mustache templates require that data is in the JSON format? The examples in the web show JSON as the source of data. Boost.Mustache says about everything convertible to json::value. It looks like the JSON input is a must. But I can see no formal specification for this. In fact, is there a one "source of truth" about mustache templates?
3. I do not see any specification (neither in Boost.Mustache docc, nor in the linked mustache(5)) for what is the required behavior when I have nested mustashes with the same name, or a JSON file with nested elements of the same name.
I'm not sure I understand this question. Do you mean things like
{{#foo}} {{#foo}} {{foo}} {{/foo}} {{/foo}}
?
If so, the way this works is that every element of data["foo"] is pushed to the top of the so-called "context stack", where entities are looked up. If this element itself contains a member "foo", this member will be used for the nested {{#foo}}. (If not, the parent "foo" will be used.)
This is what I would expect. And apparently you also. But are you explaining your implementation or the "formal specification" of mustache templates? Regards, &rzej;
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Andrzej Krzemienski wrote:
These are described here: https://github.com/mustache/spec
Thanks.
...
Ok, so this explains what Boost.Mustache does today. But on a higher level, does the *specification* for mustache templates require that data is in the JSON format? The examples in the web show JSON as the source of data. Boost.Mustache says about everything convertible to json::value.
It looks like the JSON input is a must. But I can see no formal specification for this. In fact, is there a one "source of truth" about mustache templates?
Yes, https://github.com/mustache/spec. Since all reference input data is in JSON format, it follows that JSON is the canonical data source for Mustache.
This is what I would expect. And apparently you also. But are you explaining your implementation or the "formal specification" of mustache templates?
Again, the "formal specification" at https://github.com/mustache/spec says this is how it works. This part specifically is in https://github.com/mustache/spec/blob/master/specs/sections.yml.
wt., 7 lut 2023 o 17:32 Peter Dimov
Andrzej Krzemienski wrote:
These are described here: https://github.com/mustache/spec
Thanks.
...
Ok, so this explains what Boost.Mustache does today. But on a higher level, does the *specification* for mustache templates require that data is in the JSON format? The examples in the web show JSON as the source of data. Boost.Mustache says about everything convertible to json::value.
It looks like the JSON input is a must. But I can see no formal specification for this. In fact, is there a one "source of truth" about mustache templates?
Yes, https://github.com/mustache/spec. Since all reference input data is in JSON format, it follows that JSON is the canonical data source for Mustache.
This is what I would expect. And apparently you also. But are you explaining your implementation or the "formal specification" of mustache templates?
Again, the "formal specification" at https://github.com/mustache/spec says this is how it works.
This part specifically is in https://github.com/mustache/spec/blob/master/specs/sections.yml.
Oh, I see. Thanks. &rzej;
On 8/02/2023 05:32, Peter Dimov wrote:
Yes, https://github.com/mustache/spec. Since all reference input data is in JSON format, it follows that JSON is the canonical data source for Mustache.
Technically, the specified input format is not JSON, but JavaScript objects -- hence allowing additional things beyond JSON such as lambdas. (Personally, I feel like the lambda support is misplaced -- instead of supporting lambdas in the input document it should support lambdas in the partials instead, keeping presentation separate from data. I understand why it doesn't, given that the default implementation assumes each partial is a dumb file; but Boost.Mustache doesn't have that limitation and could do better...) Mustache also has a canonical output format -- it is intended only to output as HTML and nothing else, since by default it incorporates HTML escaping rules (although that can be selectively disabled, so *technically* it can be abused to output other things). I kind of feel like a more general-purpose templating language might be more useful, but I don't have any particular preference and I don't regard this as a valid reason for rejection.
wt., 7 lut 2023 o 15:31 Andrzej Krzemienski
Hi Everyone,
I wanted to share my initial thoughts after reading the docs for the proposed Boost.Mustache.
If some library docs said "I am implementing JSON", I more-less know what to expect, because JSON is popular, I used it, so one can reliably predict what the library delivers.
This is not the case with Mustache. It is the first time I have heard this name. Apparently, it is a less popular thing. Therefore, I would expect some more introduction than just an external link. The linked page also doesn't contain sufficient information but further links. For instance to https://mustache.github.io/mustache.5.html, but this information also doesn't help me find answers to my questions:
1. What is considered an "optional part" of mustache? Boost.Mustache says it only implements the non-optional parts, but docs in mustache(5) do not indicate the optional parts.
2. It is clear to me that the procedure takes a template (with mustaches) and the data to be replaced. But what is the range of the acceptable formats of this data? The examples show that it is JSON, but does it have to be JSON? Boost.Mustache docs say it could be 'described' classes? But is that all? How about Boost.PropertyTree? What does the specification for Mustache say about it?
3. I do not see any specification (neither in Boost.Mustache docc, nor in the linked mustache(5)) for what is the required behavior when I have nested mustashes with the same name, or a JSON file with nested elements of the same name.
Or did I miss this description?
Some further notes on the documentation https://pdimov.github.io/mustache/doc/html/mustache.html#overview_descriptio... "At the moment it doesn’t implement any of the extensions.". This seems to imply that in the future the plan is to support the extensions. The only extension that I am aware of is lambdas. But I do not see how lambdas can be implemented in the library if it is using boost::json for providing data. Lambdas are not part of the JSON format at all. Which indicates that mustache templates do not typically use JSON for providing the data. This SO question shows that other languages pass data (including lambdas) directly. https://stackoverflow.com/questions/16950587/how-does-one-use-lambdas-on-the... Putting JSON as the only data type seems to set the limits on future extensions. Or is the plan to extend the data formats beyond JSON? Next, going back to the nested objects, in the description of renderer constructor we have: (https://pdimov.github.io/mustache/doc/html/mustache.html#ref_constructor) Converts data to boost::json::value by boost::json::value_from(data, sp) and stores it at the top of the *context stack*. It refers to "context stack", but this term is never explained. Next, in the same section we have: Converts partials to boost::json::object by boost::json::value_from(partials, sp).as_object() and stores it. It is far from obvious to me why the 'partials' should be converted to a json::value. Conceptually, you should only require a map of names onto texts. But json::value allows too much. According to the specs, the following should is valid: boost::mustache::render( html, std::cout, ref, { {"header", header}, {"footer", 1}, {"item", true}, {"body", nullptr} } ); But it shouldn't be valid. Or amI wrong? Regards, &rzej;
Andrzej Krzemienski wrote:
Some further notes on the documentation
https://pdimov.github.io/mustache/doc/html/mustache.html#overview_desc ription "At the moment it doesn’t implement any of the extensions.".
This seems to imply that in the future the plan is to support the extensions. The only extension that I am aware of is lambdas. But I do not see how lambdas can be implemented in the library if it is using boost::json for providing data.
I intend to implement the dynamic names extension: https://github.com/mustache/spec/blob/master/specs/~dynamic-names.yml It's simple, but very useful.
Next, in the same section we have:
Converts partials to boost::json::object by boost::json::value_from(partials, sp).as_object() and stores it.
It is far from obvious to me why the 'partials' should be converted to a json::value.
That's to allow C++ types to be passed in, such as std::map
Conceptually, you should only require a map of names onto texts. But json::value allows too much. According to the specs, the following should is valid:
boost::mustache::render( html, std::cout, ref, { {"header", header}, {"footer", 1}, {"item", true}, {"body", nullptr} } );
But it shouldn't be valid. Or amI wrong?
The specification doesn't really say what happens when the partial isn't a string. I haven't checked what other implementations do in this case.
Conceptually, you should only require a map of names onto texts. But json::value allows too much. According to the specs, the following should is valid:
boost::mustache::render( html, std::cout, ref, { {"header", header}, {"footer", 1}, {"item", true}, {"body", nullptr} } );
But it shouldn't be valid. Or amI wrong?
The specification doesn't really say what happens when the partial isn't a string. I haven't checked what other implementations do in this case.
For reference, the JS implementation will just throw an error
(they don't test that case ;)).
Reading their code, their partials has a type equivalent to:
variant<
map
I support the idea of getting rid of json::value for partials and get something more constrained. Regards, Ruben.
On Wed, Feb 8, 2023 at 3:49 AM Ruben Perez via Boost
I support the idea of getting rid of json::value for partials and get something more constrained.
I'm glad someone said it. The more time that passes, the less I like this tying of Boost.Mustache to Boost.JSON. What if there was some abstract interface // represents an individual key/value pair struct partial { string_view key; virtual void render_value( std::string& ) = 0; }; and a concept to adapt any forward range or map of key/value pairs. We could do interesting things here if we escape the JSON straightjacket. For example we could allow any user defined type T that supports operator<< to be used as a value, this neatly expands the set of supported types without the need to use Describe on them. Asio's IP addresses would work out of the box (and most of the types from Boost.URL). If we carefully craft concepts for generic values and ranges/maps of key value pairs, support for Boost.JSON types should naturally emerge without the need to write it explicitly. Thanks
On Wed, 8 Feb 2023 at 13:11, Vinnie Falco
On Wed, Feb 8, 2023 at 3:49 AM Ruben Perez via Boost
wrote: I support the idea of getting rid of json::value for partials and get something more constrained.
I'm glad someone said it. The more time that passes, the less I like this tying of Boost.Mustache to Boost.JSON.
Please note that my message was only referring to partials, which seem to only be a string -> string mapping. I've mentioned nothing on the actual data passed to be interpolated. I can see benefits in both Vinnie's and Peter's approaches there. Regards, Ruben.
On Wed, Feb 8, 2023 at 5:10 AM Ruben Perez
Please note that my message was only referring to partials, which seem to only be a string -> string mapping.
Yeah fair, and also note that my idea about converting any T with op<< to a string for substitutions applied more to the data map than the partials. Thanks
On 9/02/2023 01:10, Vinnie Falco wrote:
I'm glad someone said it. The more time that passes, the less I like this tying of Boost.Mustache to Boost.JSON.
If you did remove the tie-in to Boost.JSON entirely, then I would definitely more strongly question why this library exists over just using mstch. (That isn't to say that there can't be a reason, but it would need to more clearly advocate its motivation.)
On Wed, Feb 8, 2023 at 3:17 PM Gavin Lambert via Boost
I would definitely more strongly question why this library exists over just using mstch.
I think we really need to stop thinking of this "mstch" as any sort of solution for anything: * It is unmaintained (last commit is 8 years ago) * No streaming input of the template * No streaming output * API locks you to std::string (no string_view) etc... "mstch" is currently unusable for my Http.Proto and no one maintaining it so it basically is worthless. Thanks
On 9/02/2023 12:23, Vinnie Falco wrote:
I think we really need to stop thinking of this "mstch" as any sort of solution for anything:
It's linked from the official Mustache site, so that gives it some authority worth of consideration (even if that consideration is "we can do better").
* It is unmaintained (last commit is 8 years ago)
Lack of commits is not necessarily an indication of a problem, if it's feature-complete and works. That it has open unaddressed issues and PRs for several years is more indicative of that, however.
* No streaming input of the template * No streaming output * API locks you to std::string (no string_view)
These are also good reasons. But it would be nice to see that in a comparison/motivation doc. :)
On Wed, Feb 8, 2023 at 5:38 PM Gavin Lambert via Boost
These are also good reasons. But it would be nice to see that in a comparison/motivation doc. :)
I agree with you here. When a library is submitted, and the accompanying documentation does not explain why X, Y, and Z alternatives are no good, it leaves a vacuum which reviewers tend to fill with the least favorable comparisons. Thanks
Gavin Lambert wrote:
If you did remove the tie-in to Boost.JSON entirely, then I would definitely more strongly question why this library exists over just using mstch.
Well one reason is that I can't use mstch in any Boost library (or tool such as boostdep, which can benefit from mustaching.)
participants (5)
-
Andrzej Krzemienski
-
Gavin Lambert
-
Peter Dimov
-
Ruben Perez
-
Vinnie Falco