Fixes #357 - Deprecate empty/notEmpty in Marko v3

This commit is contained in:
Patrick Steele-Idem 2016-08-19 13:20:54 -06:00
parent 78a73e573e
commit bd488be548
21 changed files with 164 additions and 47 deletions

View File

@ -12,7 +12,7 @@ Marko is a [_really_ fast](https://github.com/marko-js/templating-benchmarks) an
# Get Involved
- **Contributing**: Pull requests are welcome!
- **Contributing**: Pull requests are welcome!
- Read [`CONTRIBUTING.md`](.github/CONTRIBUTING.md) and check out our [bite-sized](https://github.com/marko-js/marko/issues?q=is%3Aissue+is%3Aopen+label%3Adifficulty%3Abite-sized) and [help-wanted](https://github.com/marko-js/marko/issues?q=is%3Aissue+is%3Aopen+label%3Astatus%3Ahelp-wanted) issues
- Submit github issues for any feature enhancements, bugs or documentation problems
- **Support**: Join our [gitter chat](https://gitter.im/marko-js/marko) to ask questions to get support from the maintainers and other Marko developers
@ -42,7 +42,38 @@ Marko supports _both_ a familiar HTML syntax, as well as a more concise indentat
Hello ${data.name}!
</h1>
<ul if(notEmpty(data.colors))>
<if(data.colors.length)>
<ul>
<for(color in data.colors)>
<li>
${color}
</li>
</for>
</ul>
</if>
<else>
<div>
No colors!
</div>
</else>
</body>
</html>
```
Alternatively, you can choose to apply rendering logic as "attributes":
```html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Marko Templating Engine</title>
</head>
<body>
<h1>
Hello ${data.name}!
</h1>
<ul if(data.colors.length)>
<li for(color in data.colors)>
${color}
</li>
@ -65,7 +96,7 @@ html lang="en"
title - Marko Templating Engine
body
h1 - Hello ${data.name}!
ul if(notEmpty(data.colors))
ul if(data.colors.length)
li for(color in data.colors)
${color}
div else
@ -86,7 +117,7 @@ html lang="en"
<h1>
Hello ${data.name}!
</h1>
ul if(notEmpty(data.colors))
ul if(data.colors.length)
li for(color in data.colors)
${color}
div else

View File

@ -46,8 +46,6 @@ require('marko/compiler').compileFile(path, function(err, src) {
```javascript
function create(__helpers) {
var str = __helpers.s,
empty = __helpers.e,
notEmpty = __helpers.ne,
escapeXml = __helpers.x,
forEach = __helpers.f,
escapeXmlAttr = __helpers.xa;
@ -57,7 +55,7 @@ function create(__helpers) {
escapeXml(data.name) +
'! ');
if (notEmpty(data.colors)) {
if (data.colors.length) {
out.w('<ul>');
forEach(data.colors, function(color) {

View File

@ -11,13 +11,13 @@ _Applying directives using attributes:_
```xml
<!-- Colors available -->
<ul if(notEmpty(colors))>
<ul if(colors.length)>
<li for(color in colors)>
${color}
</li>
</ul>
<!-- No colors available-->
<div if(empty(colors))>
<div else>
No colors!
</div>
```
@ -26,7 +26,7 @@ _Applying directives using elements:_
```xml
<!-- Colors available -->
<if(notEmpty(colors))>
<if(colors.length)>
<ul>
<for(color in colors)>
<li>
@ -37,11 +37,11 @@ _Applying directives using elements:_
</if>
<!-- No colors available -->
<if(empty(colors))>
<else>
<div>
No colors!
</div>
</if>
</else>
```
The disadvantage of using elements to control structural logic is that they change the nesting of the elements which can impact readability. For this reason it is often more suitable to apply directives as attributes.
@ -851,9 +851,11 @@ Usage inside template:
Aside from custom helpers that can be built per-project, Marko has some built-in helpers with support for common tasks.
__empty()/notEmpty()__
## `empty()`/`notEmpty()`
To deal with "empty" data, Marko provides the empty() and notEmpty() helpers. Both helpers can be used to check for empty objects (objects, that are set to null), arrays of length zero or empty strings; empty() returns true for these cases exclusively. Therefore, not all "falsy" JavaScript values are reported as "empty" - e.g.: a boolean value that is set to "false" is not empty, hence notEmpty() would return "true". As their name already suggests, both helpers are contrary to each other.
___DEPRECATED - Do not use (removed in Marko v4)___
To deal with "empty" data, Marko automatically provides the `empty()` and `notEmpty()` helpers. Both helpers can be used to check for empty objects (objects, that are set to null), arrays of length zero or empty strings; `empty()` returns `true` for these cases exclusively. Therefore, not all "falsey" JavaScript values are reported as "empty" - e.g.: a boolean value that is set to "false" is not empty, hence `notEmpty()` would return "true". As their name already suggests, both helpers are contrary to each other.
# Miscellaneous

View File

@ -127,7 +127,7 @@ Source: https://github.com/marko-js/templating-benchmarks
<!-- Welcome to Marko! -->
<app-hello name=data.name/>
<ul if(notEmpty(data.colors))>
<ul if(data.colors.length)>
<li for(color in data.colors)>
${color}
</li>
@ -151,7 +151,7 @@ html lang="en"
body
// Welcome to Marko!
app-hello name=data.name
ul if(notEmpty(data.colors))
ul if(data.colors.length)
li for(color in data.colors)
${color}
div else
@ -171,7 +171,7 @@ html lang="en"
body
// Welcome to Marko!
<app-hello name=data.name/>
ul if(notEmpty(data.colors))
ul if(data.colors.length)
li for(color in data.colors)
${color}
div else
@ -852,7 +852,7 @@ Usage:
```xml
<my-custom-tag name="World"/>
<ul if(notEmpty(data.colors))>
<ul if(data.colors.length)>
<li for(color in data.colors)>
${color}
</li>
@ -877,7 +877,7 @@ function create(__helpers) {
name: "World"
}, out);
if (notEmpty(data.colors)) {
if (data.colors.length) {
out.w("<ul>");
forEach(data.colors, function(color) {

View File

@ -36,7 +36,7 @@ Syntax highlighting is available in the following editors and IDEs:
Hello ${data.name}!
</h1>
<ul if(notEmpty(data.colors))>
<ul if(data.colors.length)>
<li for(color in data.colors)>
${color}
</li>
@ -59,7 +59,7 @@ html lang="en"
title - Marko Templating Engine
body
h1 - Hello ${data.name}!
ul if(notEmpty(data.colors))
ul if(data.colors.length)
li for(color in data.colors)
${color}
div else
@ -80,7 +80,7 @@ html lang="en"
<h1>
Hello ${data.name}!
</h1>
ul if(notEmpty(data.colors))
ul if(data.colors.length)
li for(color in data.colors)
${color}
div else
@ -95,7 +95,7 @@ _hello-world.marko:_
```xml
<h2>Hello ${data.name}!</h2>
<ul if(notEmpty(data.colors))>
<ul if(data.colors.length)>
<li style="color: ${color}" for(color in data.colors)>
${color}
</li>
@ -195,7 +195,7 @@ __Marko:__
```xml
<h2>Hello ${data.name}!</h2>
<ul if(notEmpty(data.colors))>
<ul if(data.colors.length)>
<li class="color" for(color in data.colors)>
${color}
</li>

View File

@ -109,7 +109,7 @@ The code snippets below show how each syntax variant compares.
Hello ${data.name}!
</h1>
<ul if(notEmpty(data.colors))>
<ul if(data.colors.length)>
<li for(color in data.colors)>
${color}
</li>
@ -133,7 +133,7 @@ html lang="en"
body
// Welcome to Marko!
h1 - Hello ${data.name}!
ul if(notEmpty(data.colors))
ul if(data.colors.length)
li for(color in data.colors)
${color}
div else
@ -186,7 +186,7 @@ html lang="en"
<h1>
Hello ${data.name}!
</h1>
ul if(notEmpty(data.colors))
ul if(data.colors.length)
li for(color in data.colors)
${color}
div else
@ -894,7 +894,7 @@ For example, given the following input template:
```xml
<my-custom-tag name="World"/>
<ul if(notEmpty(data.colors))>
<ul if(data.colors.length)>
<li for(color in data.colors)>
${color}
</li>
@ -921,7 +921,7 @@ function create(__helpers) {
name: "World"
}, out);
if (notEmpty(data.colors)) {
if (data.colors.length) {
out.w("<ul>");
forEach(data.colors, function(color) {

4
helpers/README.md Normal file
View File

@ -0,0 +1,4 @@
Marko Helpers
=============
This directory contains helpers that were deprecated in Marko v3.

5
helpers/empty.js Normal file
View File

@ -0,0 +1,5 @@
var notEmpty = require('./notEmpty');
module.exports = function (o) {
return !notEmpty(o);
};

11
helpers/notEmpty.js Normal file
View File

@ -0,0 +1,11 @@
module.exports = function notEmpty(o) {
if (o == null) {
return false;
} else if (Array.isArray(o)) {
return !!o.length;
} else if (o === '') {
return false;
}
return true;
};

23
runtime/deprecate.js Normal file
View File

@ -0,0 +1,23 @@
var logger = typeof console !== 'undefined' && console.warn && console;
module.exports = function(o, methodName, message) {
if (!logger) {
return;
}
var originalMethod = o[methodName];
var maxWarn = 20;
var currentWarn = 0;
o[methodName] = function() {
if (currentWarn < maxWarn) {
if (++currentWarn === maxWarn) {
o[methodName] = originalMethod;
}
logger.warn(message, 'Stack: ' + new Error().stack);
}
return originalMethod.apply(o, arguments);
};
};

View File

@ -1,18 +1,20 @@
var copyProp;
var maxWarn = 50;
var maxWarn = 20;
var currentWarn = 0;
var logger = typeof console !== 'undefined' && console.warn && console;
function deprecateWarning(deprecatedName) {
console.warn('Deprecated: Use the unhyphenated name instead for reading "' + deprecatedName +
'" - WARNING: This will not be allowed in the future.');
logger.warn('Deprecated: Use the unhyphenated name instead for reading "' + deprecatedName +
'" - WARNING: This will not be allowed in the future. Stack: ' + new Error().stack);
}
function copyPropNoWarn(obj, deprecatedName, targetName) {
obj[deprecatedName] = obj[targetName];
}
if (Object.defineProperty) {
if (logger && Object.defineProperty) {
copyProp = function(obj, deprecatedName, targetName) {
Object.defineProperty(obj, deprecatedName, {
get: function() {

View File

@ -19,23 +19,13 @@ var escapeXml = require('raptor-util/escapeXml');
var escapeXmlAttr = escapeXml.attr;
var runtime = require('./'); // Circular dependency, but that is okay
var attr = require('raptor-util/attr');
var notEmpty = require('../helpers/notEmpty');
var isArray = Array.isArray;
var STYLE_ATTR = 'style';
var CLASS_ATTR = 'class';
var escapeEndingScriptTagRegExp = /<\//g;
function notEmpty(o) {
if (o == null) {
return false;
} else if (Array.isArray(o)) {
return !!o.length;
} else if (o === '') {
return false;
}
return true;
}
function classListHelper(arg, classNames) {
var len;
@ -114,7 +104,7 @@ function LoopStatus(getLength, isLast, isFirst, getIndex) {
this.getIndex = getIndex;
}
module.exports = {
module.exports = exports = {
/**
* Internal helper method to prevent null/undefined from being written out
* when writing text that resolves to null/undefined
@ -188,7 +178,7 @@ module.exports = {
* Internal method to check if an object/array is empty
* @private
*/
e: function (o) {
e: function empty(o) {
return !notEmpty(o);
},
/**
@ -398,3 +388,8 @@ module.exports = {
return classList(arguments);
}
};
var deprecate = require('./deprecate');
var emptyNotEmptyDeprecationUrl = 'https://github.com/marko-js/marko/issues/357';
deprecate(exports, 'e', 'empty() helper is deprecated. See: ' + emptyNotEmptyDeprecationUrl);
deprecate(exports, 'ne', 'notEmpty() helper is deprecated. See: ' + emptyNotEmptyDeprecationUrl);

View File

@ -0,0 +1 @@
<div>0</div><div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div><div>11</div><div>12</div><div>13</div><div>14</div><div>15</div><div>16</div><div>17</div><div>18</div><div>19</div><div>20</div><div>21</div><div>22</div><div>23</div><div>24</div><div>25</div><div>26</div><div>27</div><div>28</div><div>29</div><div>30</div><div>31</div><div>32</div><div>33</div><div>34</div><div>35</div><div>36</div><div>37</div><div>38</div><div>39</div><div>40</div><div>41</div><div>42</div><div>43</div><div>44</div><div>45</div><div>46</div><div>47</div><div>48</div><div>49</div><div>50</div>

View File

@ -0,0 +1,5 @@
<for(var i=0; i<51; i++)>
<div if(notEmpty(['a', 'b', 'c']))>
${i}
</div>
</for>

View File

@ -0,0 +1,3 @@
exports.templateData = {
"name": "John"
};

View File

@ -0,0 +1 @@
<div>notEmpty-YES</div><div>empty-YES</div>

View File

@ -0,0 +1,12 @@
<div if(notEmpty(['a', 'b', 'c']))>
notEmpty-YES
</div>
<div if(notEmpty([]))>
notEmpty-NO
</div>
<div if(empty(['a', 'b', 'c']))>
empty-NO
</div>
<div if(empty([]))>
empty-YES
</div>

View File

@ -0,0 +1,3 @@
exports.templateData = {
"name": "John"
};

View File

@ -0,0 +1 @@
<div>notEmpty-YES</div><div>empty-YES</div>

View File

@ -0,0 +1,17 @@
<script marko-init>
var notEmpty = require('marko/helpers/notEmpty');
var empty = require('marko/helpers/empty');
</script>
<div if(notEmpty(['a', 'b', 'c']))>
notEmpty-YES
</div>
<div if(notEmpty([]))>
notEmpty-NO
</div>
<div if(empty(['a', 'b', 'c']))>
empty-NO
</div>
<div if(empty([]))>
empty-YES
</div>

View File

@ -0,0 +1,3 @@
exports.templateData = {
"name": "John"
};