Repository: mozilla/nunjucks
Pull request #428 (2015-05-01 22:12:05)

add "loose" option to default filter, add warning about change
@carljm how does this look? I basically warn people about the change and tell them to check their filters. if they are sure it's not going to affect them they can ignore the warning.

I also am not checking specifically for `false` when it is "loose", but any falsy JS value will return the default. Is that sane?

That's the kind if thing that might differ under a "jinja" compat mode... truthiness is the hardest thing to reconcile.


Patch:
diff --git a/docs/templating.md b/docs/templating.md
index 8bf98f6..013a67f 100644
--- a/docs/templating.md
+++ b/docs/templating.md
@@ -702,13 +702,37 @@ If `tags` was `["food", "beer", "dessert"]`, the above example would output `foo
 
 ## Builtin Filters
 
-Nunjucks has ported most of jinja's filters (click through for documentation):
+Nunjucks has ported most of jinja's filters, and has a few of its own.
+We need to work on our own documentation for filters. Some of them are
+documented below, for the rest you can click through to jinja's site.
+
+### default(value, default, [boolean])
+
+(aliased as `d`)
+
+If `value` is strictly `undefined`, return `default`, otherwise
+`value`. If `boolean` is true, any JavaScript falsy value will return
+`default` (false, "", etc)
+
+**In version 2.0, `loose` is required because this filter changed from
+  loose by default to strict by default. A warning will be display if
+  you don't specify loose, and once we've warned everyone of the
+  change we will remove the warning. If you are sure this change won't 
+  affect you, ignore this warning.**
+
+### sort(arr, reverse, caseSens, attr)
+
+Sort `arr` with JavaScript's `arr.sort` function. If `reverse` is
+true, result will be reversed. Sort is case-insensitive by default,
+but setting `caseSense` to true makes it case-sensitive. If `attr` is
+passed, will compare `attr` from each item.
+
+### More Filters
 
 * [abs](http://jinja.pocoo.org/docs/templates/#abs)
 * [batch](http://jinja.pocoo.org/docs/templates/#batch)
 * [capitalize](http://jinja.pocoo.org/docs/templates/#capitalize)
 * [center](http://jinja.pocoo.org/docs/templates/#center)
-* [default](http://jinja.pocoo.org/docs/templates/#default) (aliased as `d`)
 * [dictsort](http://jinja.pocoo.org/docs/templates/#dictsort)
 * [escape](http://jinja.pocoo.org/docs/templates/#escape) (aliased as `e`)
 * [safe](http://jinja.pocoo.org/docs/templates/#safe)
@@ -727,7 +751,6 @@ Nunjucks has ported most of jinja's filters (click through for documentation):
 * [round](http://jinja.pocoo.org/docs/templates/#round)
 * [selectattr](http://jinja.pocoo.org/docs/templates/#selectattr) (only the single-argument form)
 * [slice](http://jinja.pocoo.org/docs/templates/#slice)
-* [sort](http://jinja.pocoo.org/docs/templates/#sort)
 * [string](http://jinja.pocoo.org/docs/templates/#string)
 * [title](http://jinja.pocoo.org/docs/templates/#title)
 * [trim](http://jinja.pocoo.org/docs/templates/#trim)
diff --git a/src/filters.js b/src/filters.js
index 9ea1839..848e0d7 100644
--- a/src/filters.js
+++ b/src/filters.js
@@ -10,6 +10,7 @@ function normalize(value, defaultValue) {
     return value;
 }
 
+var hasWarnedDefault = false;
 
 var filters = {
     abs: function(n) {
@@ -63,8 +64,25 @@ var filters = {
         return r.copySafeness(str, pre + str + post);
     },
 
-    'default': function(val, def) {
-        return val ? val : def;
+    'default': function(val, def, bool) {
+        if(bool !== true && bool !== false && !hasWarnedDefault) {
+            hasWarnedDefault = true;
+            console.log(
+                '[nunjucks] Warning: the "default" filter was used without ' +
+                'specifying the type of comparison. 2.0 changed the default ' +
+                'behavior from boolean (val ? val : def) to strictly undefined, ' +
+                'so you should make sure that doesn\'t break anything. ' +
+                'Be explicit about this to make this warning go away, or wait until 2.1. ' +
+                'See http://mozilla.github.io/nunjucks/templating.html#defaultvalue-default-loose'
+            );
+        }
+
+        if(bool) {
+            return val ? val : def;
+        }
+        else {
+            return (val !== undefined) ? val : def;
+        }
     },
 
     dictsort: function(val, case_sensitive, by) {


Test patch:
diff --git a/tests/express-sample/views/index.html b/tests/express-sample/views/index.html
index c1e4a83..b43ea91 100644
--- a/tests/express-sample/views/index.html
+++ b/tests/express-sample/views/index.html
@@ -1,7 +1,7 @@
 {% extends "base.html" %}
 
 {% block content %}
-Hello, {{ username }}! This is just some content.
+Hello, {{ username | default('poop') }}! This is just some content.
 
 <div id="dynamic"></div>
 {% endblock %}
diff --git a/tests/filters.js b/tests/filters.js
index 8219bdb..c1e141a 100644
--- a/tests/filters.js
+++ b/tests/filters.js
@@ -76,7 +76,11 @@
         });
 
         it('default', function(done) {
-            equal('{{ false | default("foo") }}', 'foo');
+            equal('{{ undefined | default("foo") }}', 'foo');
+            equal('{{ bar | default("foo") }}', { bar: null }, '');
+            equal('{{ false | default("foo") }}', 'false');
+            equal('{{ false | default("foo", true) }}', 'foo');
+            equal('{{ bar | default("foo") }}', 'foo');
             equal('{{ "bar" | default("foo") }}', 'bar');
             finish(done);
         });