Closed tajmone closed 5 years ago
Hello,
This could be interesting. But there are a few questions that should be asked:
I think the inputs of mustache must be preprocess by pp, not the output to be consistent with other macros. If the output needs to be preprocessed as well, it can be done with the !pp
macro.
I hadn't thought of this.
Probably in most use-case scenarios the YAML/JSON file wouldn't need to be preprocessed as it's going to be a plain YAML/JSON file.
As for the template, having PP preprocess the input would be an added bonus, and I agree with the consistency approach.
If the output needs to be preprocessed as well, it can be done with the
!pp
macro.
Do you mean by this !pp
macros WRAPPING the whole mustache block, macro included? like this:
!pp
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!mustache(macros.yaml)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{{#macros}}
!{{macro}}
{{/macros}}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I'm trying to imagine the pros and cons of PP processing the input of !mustache
before it's fed to mustache....
This should mean that PP macros could be used to affect the mustache tags BEFORE the template gets processed. Something like:
!mustache(foods.yaml)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{{#!type}}
{{item}}!
{{/!type}}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
... where the !type
custom macro could be used to alter the mustache tag and output different item
s — assuming foods.yaml
:
fruit: [ {item: apple}, {item: banana}, {item: pear} ]
cheese: [ {item: Cheddar}, {item: Mozzarella}, {item: Roquefort} ]
... we could set !type
to fruit
or cheese
and produce different lists from the same YAML source file.
More complex scenarios might envolve the mustache expanded variables being used as PP macros AFTER !mustache
has done its job:
!mustache(macros.yaml)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{{#macros}}
!{{macro}}
{{/macros}}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
With "macros.yaml
":
macros: [ {macro: xxx}, {macro: yyy}, {macro: zzz} ]
... where the post-processed (!mustache
) block will produce PP macros:
!xxx
!yyy
!zzz
So, in order for these to be preprocessed it would be necessary to wrap the whole thing in !pp
, right? As in:
!pp
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!mustache(macros.yaml)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{{#macros}}
!{{macro}}
{{/macros}}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Am I getting it right? I'm not sure I understand well how PP would handle nested macros in this scenario.
...
Probably these are far-fetched examples, but they exemplify the added extra power to PP usage that mustache would introduce — of course there might be many other ways that interaction between PP and mustache could be exploited to get cool results.
You're right, this has to be though about beforehand.
Another thing I was wondering is if it was possible to also support Lambdas, and how. From mustache documentation:
Lambdas
When the value is a callable object, such as a function or lambda, the object
will be invoked and passed the block of text. The text passed is the literal
block, unrendered. {{tags}} will not have been expanded - the lambda should do
that on its own. In this way you can implement filters or caching.
Template:
{{#wrapped}}
{{name}} is awesome.
{{/wrapped}}
Hash:
{
"name": "Willy",
"wrapped": function() {
return function(text, render) {
return "<b>" + render(text) + "</b>"
}
}
}
Output:
<b>Willy is awesome.</b>
I think that the above refers to the Ruby implementation, and that different mustache implementation either support it differently or don't support it at all.
How does the Haskell mustache implementation deal with Lambdas? does it support Haskell callable objects/functions?
The haskell implementation seems to support lambda but functions must be defined as Haskell expressions which must be compiled. Embedding a Haskell compiler in pp is not desirable.
It may be possible to use pp macros as lambda expressions but it is easier to mix pp macros and mustache templates:
!def(wrapped)(<b>!1</b>)
!mustache
~~~
!wrapped(
{{name}} is awesome.
)
~~~
I will check if it is possible to write such things to define lambdas as pp macros:
{
"name": "Willy",
"wrapped": "<b>!1<b>"
}
The haskell implementation seems to support lambda but functions must be defined as Haskell expressions which must be compiled. Embedding a Haskell compiler in pp is not desirable.
I feared it might be so, but I was hoping that somehow it was possible to rely on pandoc's built-in support of Haskell (as filters, ecc.); but it was a far-stretched hope.
It may be possible to use pp macros as lambda expressions ...
I thought of that but I wasn't sure about how inline macro definition and passed parameters could be handled, but your example provides a good usage example.
The potential of mustache integration seems promising; overlapping interaction of PP macros and mustache tags enhance the power of both systems as they allow creating complex contexts where the two are intertependent and interweaved. This should allow simple and fine-tuned customization of documents output by tweaking/swapping human-readable YAML configuration files.
Looking forward to it!
The problem using pp macros as lambda is that it would require some changes in the Haskell libraries (mustache as well as aeson). I think I'll stick to my first proposal (using pp macros in the mustache template and preprocessing it before calling mustache).
pp 2.6 has been released. It provides the mustache
macro.
Thanks Christophe!
Would it be possible to integrate [mustache] into PP with a built-in macro like:
... where the macro will load the YAML (or JSON) file of the 1st parameter and use its variables to preprocess the text inside 2nd parameter.
Usage Example
Based on the examples found at mustache website, suppose we have a YAML file
example.yaml
:... and in our source document the macro:
... PP's output should be:
Haskell Mustache
There is a Haskell implementation of mustache:
So, hopefully it could be integrated into PP natively, without requiring the end user to install any mustache version on his system.
Probably, it might not be possible to integreate into this macro some of mustache's advanced features (like Lambdas, Partials and Set Delimiter tags), for they require a complex interaction with the environment; but if the rest of the basic features could be integrated it would be good enough — and, IMO, well worth it.
Benefits
I think that mustache's logicless templating system would be a great added bonus to PP's powers, for some templating operations are easier (and less verbose) in mustache.
Also, it would allow to incorporate into projects existing mustache/YAML resources. For example, Base16 color schemes could be used via this macro to produce inline CSS in the final HTML document, to define syntax highlighting colors. But the potential uses are quite broad, for this new macro could be used anywhere in a source document, including YAML headers.
...
What do you think of it Crhistophe?