Filters implementation. #102

Merged
merged 7 commits into from Oct 27, 2012

Conversation

Projects
None yet
4 participants
@bobthecow
Owner

bobthecow commented Jul 28, 2012

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',
]);
@thelucid

This comment has been minimized.

Show comment
Hide comment
@thelucid

thelucid Aug 9, 2012

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

thelucid commented Aug 9, 2012

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

@rafi

This comment has been minimized.

Show comment
Hide comment
@rafi

rafi 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.

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

This comment has been minimized.

Show comment
Hide comment
@groue

groue 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?

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

1 check passed

default The Travis build passed
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment