Skip to content

Conversation

@bobthecow
Copy link
Owner

re: mustache/spec#41

Comment here for discussion around merging this feature into the dev branch, comment there for getting it added to the Mustache spec.

Since I've got a pragma flag on this one, I'm not opposed to merging it before it gets approved for the spec, but — unless this gets approved exactly as I have implemented — that will most likely result in backwards compatibility breaks down the line, which I do prefer to avoid.

The assumptions here are that:

  1. Pipe notation is analogous to dot notation — it can be thought of as syntactic sugar for nested sections.
  2. Filters are just variables in the normal context stack.
  3. Values are not coerced into strings (or escaped) until they come out the other end of the pipe.
  4. Unlike nested sections, the first value in the pipe is fetched prior to passing it to the next lambda.
  5. If any filter is not found, or is non-callable, an UnexpectedValueException is thrown.

Also:

  • Filters don't get parameters. That's logic in your template. See the commentary in the spec issue regarding {{ foo | date.iso8601 }} vs {{ foo | date: "%j. %F %Y" }} (or whatever).
  • Since this is a non-spec feature, it is toggled with a {{%FILTERS}} pragma tag.

In code:

<?php

$mustache = new Mustache_Engine;

$tpl = <<<TPL
{{%FILTERS}}
{{ greeting | case.lower }}, {{ planet | case.upper | !! }}
TPL;

$mustache->render($tpl, [
    'greeting' => 'Hello',
    'planet' => 'world',
    'case' => [
        'lower' => function($value) { return strtolower((string) $value); },
        'upper' => function($value) { return strtoupper((string) $value); },
    ],
    '!!' => function($value) { return $value . '!!'; }
]);

// hello, WORLD!!

Or (more likely if you're using Mustache.php's helper injection feature):

<?php

$mustache = new Mustache_Engine;
$mustache->addHelper('case', [
    'lower' => function($value) { return strtolower((string) $value); },
    'upper' => function($value) { return strtoupper((string) $value); },
]);
$mustache->addHelper('!!', function($value) { return $value . '!!'; });

$tpl = <<<TPL
{{%FILTERS}}
{{ greeting | case.lower }}, {{ planet | case.upper | !! }}
TPL;

$mustache->render($tpl, [
    'greeting' => 'Hello',
    'planet'   => 'world',
]);

@ghost
Copy link

ghost commented Aug 9, 2012

Definitely prefer this to the Liquid style filters as it sticks more to the logicless template philosophy. +1.

@rafi
Copy link

rafi commented Aug 9, 2012

The thing I love about Mustache is that it's so simple, I see how this can really be a way for abuse, however, I would very much be glad to see this merged. The pargma gives us a choice and filters could really help with i18n.

@groue
Copy link

groue commented Sep 29, 2012

@bobthecow: the parenthesis syntax used by GRMustache lets users write meta-filters: https://gist.github.com/3803707

Surely some GRMustache assumptions are different, and particularly, filters are not syntactic sugar for nested sections: they are value transformers, and f(x) is an expression that has a value in the current context just as x and x.y.

However I totally agree on those:

  • Values are not coerced into strings (or escaped) until they are rendered.
  • If any filter is not found, or is non-callable, an UnexpectedValueException is thrown.

On the last one below, I am reserved. GRMustache doesn't load filters in the context stack, in order to avoid a filter to change meaning in the middle of the rendering.

Filters are just variables in the normal context stack.

Thoughts?

bobthecow added a commit that referenced this pull request Oct 27, 2012
@bobthecow bobthecow merged commit 010e360 into dev Oct 27, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants