├── readme.md ├── data-driven-tests-in-javascript-using-mocha.md ├── how-to-build-and-publish-es6-npm-modules-today-with-babel.md ├── csharp-6-an-introduction.md └── input-validation-in-express-with-express-validator.md /readme.md: -------------------------------------------------------------------------------- 1 | Here is the thing: my [website](https://github.com/TryGhost/Ghost) is powered by [Ghost](https://github.com/TryGhost/Ghost). Ghost is :cool: but I need _somewhere_ to back up my articles... 2 | 3 | ... because I write all my posts in markdown _anyway_ I thought I might as well back them up, right here, in this GitHub repo'. 4 | -------------------------------------------------------------------------------- /data-driven-tests-in-javascript-using-mocha.md: -------------------------------------------------------------------------------- 1 | *Welcome to this article in which I'll teach you how to write data-driven tests using [Mocha](https://mochajs.org/).* 2 | 3 | *If you are already familiar with the data-driven test pattern, you may wish to skip the proceeding section and jump straight to the [sections on implementation](#implementation).* 4 | 5 | ## The Case for Data-Driven Tests 6 | 7 | Sometimes it's desirable to run essentially the same test many times with many slightly different inputs. 8 | 9 | Imagine for a second that you're writing a function called `isPrime` that takes a number. This function should return `true` if the number is prime; otherwise, it should return `false`. Here is what our tests for such a function might look like, using Mocha and [Chai](http://chaijs.com/): 10 | 11 | ```javascript 12 | import { expect } from "chai"; 13 | import isPrime from "./"; 14 | 15 | describe("isPrime()", function() { 16 | it("should return true when number is a prime number", function() { 17 | const actual = isPrime(2); 18 | expect(actual).to.be.true; 19 | }); 20 | 21 | test("should return false when number is a composite number", function() { 22 | const actual = isPrime(4); 23 | expect(actual).to.be.false; 24 | }); 25 | }); 26 | ``` 27 | 28 | What do you think about these tests? Do you think that they're adequate? 29 | 30 | I don't think these tests are very good at all. Here's why: 31 | 32 | At the moment, all these tests prove is that the function returns `true` if the input is `2`, or `false` if the input is `4`. 33 | 34 | The `isPrime` function's implementation could be as erroneous as: 35 | 36 | ```javascript 37 | export default function isPrime(num) { 38 | if (num === 2) { 39 | return true; 40 | } else { 41 | return false; 42 | } 43 | } 44 | ``` 45 | 46 | and the tests would still pass. 47 | 48 | Clearly our test coverage is inadequate - we'll need to add more tests if we are ever going to trust our test suite to catch [regressions](https://en.wikipedia.org/wiki/Software_regression). 49 | 50 | Now, what we *could* do is duplicate the tests a handful of times, changing the input slightly for each test: 51 | 52 | ```javascript 53 | import { expect } from "chai"; 54 | import isPrime from "./"; 55 | 56 | describe("isPrime", function() { 57 | test("given a prime number, isPrime() returns true", function() { 58 | const actual = isPrime(2); 59 | expect(actual).to.be.true; 60 | }); 61 | 62 | test("given a prime number, isPrime() returns true", function() { 63 | const actual = isPrime(5); 64 | expect(actual).to.be.true; 65 | }); 66 | 67 | test("given a prime number, isPrime() returns true", function() { 68 | const actual = isPrime(727); 69 | expect(actual).to.be.true; 70 | }); 71 | 72 | test("given a prime number, isPrime() returns true", function() { 73 | const actual = isPrime(1223); 74 | expect(actual).to.be.true; 75 | }); 76 | }); 77 | ``` 78 | 79 | Whilst this approach provides much better code coverage of functionality, it also incurs a high cost to test maintainability, due to the repetitious nature of the tests. Repetitious tests are untenable because any changes made to one of the tests must be propagated to all of the similar tests. In other words, this approach violates the [DRY principle](), which isn't good. 80 | 81 | This is a common problem, for which a solution already exists. Enter the *data-driven test pattern*. 82 | 83 |
88 | {
89 | "main": "./distribution/index.js",
90 | "scripts": {
91 | "build": ...
92 | }
93 | }
94 |
95 | ## Ignoring files
96 |
97 | You're almost ready to publish your Node module, but first you're going to want to tell npm to not upload the `source` folder by creating an `.npmignore` file with the following contents:
98 |
99 | ```
100 | source
101 | ```
102 |
103 | Similarly, you'll want to tell Git to not upload the `distribution` folder. You can do this by adding the below lines to your `.gitignore` file:
104 |
105 | ```
106 | node_modules
107 | distribution
108 | ```
109 |
110 | **Heads up!** It is very important that, if you have a `.gitignore` file, that you also have an `.npmignore` file. If you don't create an `.npmignore` file, npm will actually use your `.gitignore` as the `.npmignore`, which means that the `distribution` folder won't be published.
111 |
112 | ### Publishing to npm
113 |
114 | Before publishing to npm, you'll firstly want to build your source files using the `build` script you defined earlier. Instead of doing this manually, I _highly_ recommend that you create a special script recognized by npm called `prepublish` that npm will automatically execute before publishing the package:
115 |
116 |
117 |
118 | "scripts": {
119 | "build": "babel-cli --preset xxx",
120 | "prepublish": "npm run build"
121 | }
122 |
123 | Now, when you run `npm publish`, npm will automatically run the `build` script. This is both convenient and helps to avoid errors.
124 |
125 |
126 | Whilst I have found `prepublish` to work fine for my needs, I feel it important to mention that there is a [known UX issue](https://github.com/npm/npm/issues/10074#issue-112707857) with `prepublish` whereby the script is implicitly run when the package is installed. This may or may not be a problem for you.
127 |
128 | If you haven't done so already, use [these instructions](https://gist.github.com/coolaj86/1318304) by [@coolaj86](https://github.com/coolaj86) to set your npm author information. Then, simply run the following command whilst in the module folder:
129 |
130 | ```
131 | npm publish ./
132 | ```
133 |
134 | After a few seconds, if you did everything correctly, your module should be published to the npm registry.
135 |
136 | ## Testing it out
137 | Before I conclude, I want to show you that developers can seamlessly install and use your module, despite the fact that it was coded using ES6.
138 |
139 | First of all, I can install the [`offof`](https://www.npmjs.com/package/offof) package just like I would any other npm package:
140 |
141 |
142 | ```
143 | npm install
144 | ```
145 | Then, from within Node 4 - an environment that has little to no notion of ES6 - I can import and use the module as though it were written in ES5:
146 |
147 | 
148 |
149 |
150 | You might also find it instructive to observe the `node_modules` directory:
151 |
152 | 
153 |
154 | As you can see, there's no trace of the `source` folder; there's only the `distribution` folder.
155 |
156 | ## Conclusion
157 |
158 | In this article you learned how to utilize the syntactic niceties afforded by ES6 whilst still maintaining support for platforms that don't yet support it. You also learned about some potential pitfalls along the way, like how you should probably use `module.exports` instead of an ES6 export statement.
159 |
160 | _Special thanks to: [Stephen Moon](https://twitter.com/s_moon_uk), [Maarten Van Giel](https://twitter.com/maartenvangiel), [Romaine Rose-Cameron](https://twitter.com/R0ma1ne), [partycoder](https://www.livecoding.tv/partycoder/), and [kevin-DL](https://github.com/kevin-DL)._
161 |
162 |
163 | **P.S. If you read this far, you might want to follow me on [Twitter](https://twitter.com/bookercodes) and [GitHub](https://github.com/alexbooker), or [subscribe](https://booker.codes/rss/) to my blog.**
164 |
--------------------------------------------------------------------------------
/csharp-6-an-introduction.md:
--------------------------------------------------------------------------------
1 | *Welcome to this series of articles in which we'll examine the details of the new features in C# 6.0. You are currently reading part 1 of 11:*
2 |
3 |
4 | 1. Introduction
5 | - Expression-Bodied Members
6 | - Auto-Implemented Property Initializers
7 | - Read-Only Auto-Implemented Properties
8 | - Null-Conditional Operator
9 | - NameOf Operator
10 | - String Interpolation
11 | - Await in Catch and Finally Blocks
12 | - Exception Filters
13 | - Index Initializers
14 | - Extension Add in Collection Initializers
15 | - Using Static Statement
16 |
17 | *In addition to these articles, I am also producing a series of free screencasts about C# 6.0 on my YouTube channel, [CodeCast](https://www.youtube.com/channel/UCcQsDUZiK1GWDcP7BpVO_kw?sub_confirmation=1). If you want to, you can check them out [here](https://www.youtube.com/playlist?list=PL5ze0DjYv5DYK391_xP1Y8Oait1-_o5x9).*
18 |
19 |
20 |
21 | ### Introduction
22 |
23 | Conventionally, each new version of C# has one super-feature, and a handful of miniature ones. For example, in the previous version of C#, C# 5.0, the super-feature was [asynchronous methods (`async`)](https://msdn.microsoft.com/en-us/library/hh156513.aspx) and the miniature features were [caller information attributes](https://msdn.microsoft.com/en-us/library/hh534540.aspx) and [improved "closures"](https://stackoverflow.com/questions/12112881/has-foreachs-use-of-variables-been-changed-in-c-sharp-5). C# 6.0 is a bit different, in that there is no super-feature, just a bunch of miniature ones.
24 |
25 | Instead of introducing a new super-feature, C# 6.0 introduces a bunch of small features that alleviate small pain points from previous versions of the language. Most of the new features in C# 6.0 will make your code simpler, leaner, more readable, and more pleasant to write, but they are unlikely to revolutionize the way you write C# like super-features (such as asynchronous methods) in earlier versions of the language have.
26 |
27 | As you'll see throughout this series, most of the new features are essentially [syntactic sugar](https://en.wikipedia.org/wiki/Syntactic_sugar) – in other words, most (but not all) of the features in C# 6.0 do not introduce new functionality, but instead enable you to do things you could already do in a more compact and readable manner.
28 |
29 | There are 11 new features in total. Here's a quick rundown of the features (in the order we'll examine them), so you know what to expect:
30 |
31 | - **Expression-Bodied Members -** Allow you to associate a single expression with a member instead of a block (much like a lambda expression, but for members).
32 | - **Auto-Implemented Property Initializers –** Allow you to initialize automatic properties with a default value, inline, much like a field initializer.
33 | - **Read-Only Auto-Implemented Properties -** Allow you to omit the `set`ter from an automatic property, which makes it read-only.
34 | - **Null-Conditional Operator –** A much more compact syntax for deep null checks.
35 | - **NameOf Operator –** Allows you to refer to an identifier (such as an argument name) in a resilient way.
36 | - **String Interpolation -** Language support for [*composite formatting*](https://msdn.microsoft.com/en-us/library/txafckwd.aspx).
37 | - **Await in Catch and Finally Blocks –** It is now possible to use `await` in catch and finally blocks.
38 | - **Exception Filters -** Allow you to conditionally enter exception handlers.
39 | - **Index Initializers –** Allow you to elegantly add elements to an indexed collection via an index.
40 | - **Extension Add in Collection Initializers –** Allow you to add elements to a collection based on an extension method called `Add` (previously, the `Add` method had to be part of the collection type.)
41 | - **Using Static Statement –** Removes the need to fully qualify public static members.
42 |
43 |
44 | While these features are unlikely to revolutionize the way you write C#, they _will_ change the way you write code in specific scenarios, due to the fact that they are so much more efficient, you'll likely forget there was another way to code them.
45 |
46 | You might be wondering why there is no super-feature this time around. Presumably, the reason is that the managed languages team were busy completing a project they first announced around 6 years ago - the [_.NET Compiler Platform_](), better known by it's code name, _Roslyn_.
47 |
48 | ### Roslyn
49 |
50 | Historically, the C# compiler was a [black box](https://en.wikipedia.org/wiki/Black_box) - you, the developer, input C# code and, if it was valid, the compiler would emit an assembly (a .exe or .dll), but the implementation of the compiler, however, was opaque:
51 |
52 | 
53 |
54 | We could never have known *exactly* what the compiler was doing internally – it was opaque - but it was safe to assume that it was doing normal compiler things: parsing source code, analysing the semantics, emitting IL, etc.:
55 |
56 | 
57 |
58 |
59 | As the source code traversed this pipeline, the compiler would develop a wealth of information about it - information about what elements are present in the code, how they relate to each other, etc. - this information, however, was private. This was unfortunate because, that information could have been of *tremendous* value to developers outside of the managed languages team. Think about tools like [SharpDevelop](), who require a deep understanding of source code - they had to rely on their own implementations to parse and analyse source code to power their features (such as syntax colorization and completion lists). Even Visual Studio had three separate makeshift language services that lacked feature parity!
60 |
61 | It would have been *so* much nicer if the compiler was 1/ open source and 2/ exposed a set of compiler APIs. As you may have guessed, now the compiler does both, through Roslyn.
62 |
63 | Roslyn is a reimagination of what a compiler should be. In a nutshell, it is a [open source](), ground-up rewrite of the Visual Basic and C# compilers in those languages themselves. In addition to providing a set of familiar compilers (csc.exe and vbc.exe), it provides a set of compiler APIs that expose rich information about the source code:
64 |
65 | 
66 |
67 | As you can see in the above illustration (which I pinched from the [Roslyn documentation](https://github.com/dotnet/roslyn/wiki/Roslyn%20Overview)), each phase in the compiler pipeline has a corresponding compiler API.
68 |
69 | This "openness" is obviously _very_ beneficial for tool developers - tools like SharpDevelop and Visual Studio can now use Roslyn to power their features instead of relying on their own makeshift implementations, which will make them more powerful.
70 |
71 | The benefits of Roslyn are not limited to traditional tools like Visual Studio. Hot open-source tools like [Omnisharp](http://www.omnisharp.net/) and [scriptcs](http://scriptcs.net/) are now powered by Roslyn. So is [dynamic development](http://weblogs.asp.net/scottgu/introducing-asp-net-5) in [ASP.NET 5](http://www.asp.net/vnext). Roslyn will also make it easier to embed C# in [domain-specific languages](), build [static analyzers](https://en.wikipedia.org/wiki/Static_program_analysis), and more! It really opens the door to a whole new world of [meta-programming](https://en.wikipedia.org/wiki/Metaprogramming) possibilities.
72 |
73 | As you can probably appreciate, porting the current compilers' code to managed code was no small undertaking. *Presumably*, it is because the managed languages team was focused on completing Roslyn that there wasn't much time for language feature innovation this time around. That being said, Roslyn will make it easier to prototype and implement new features, so we'll likely see a quicker turn-around for language innovation going forward.
74 |
75 | > #### Why the name Roslyn?
76 | > A small piece of trivia is that the code name Roslyn was inspired by the name of a small town in Washington called [Roslyn](https://en.wikipedia.org/wiki/Roslyn,_Washington), which is about an hours drive from the Microsoft campus in Seattle.
77 |
78 | I shan't belabour Roslyn in this article because, while Roslyn is a very interesting topic, understanding it will not particularly help your understanding of C# 6.0, which is the focus of these articles.
79 |
80 | We're nearly ready to dive into C# 6.0, but before we do, I want to briefly explain a couple of technical details relating to the differences between the compiler, the runtime, and the framework libraries. If these details are familiar to you, I apologize - you should feel free to skip to the conclusion - but these topics have been the cause of a lot of confusion in the past.
81 |
82 | ### Dissecting the .NET Framework
83 |
84 | It is important to understand that the C# compiler, while part of the .NET Framework, is versioned separately to the runtime and framework libraries.
85 |
86 | 
87 |
88 | The *C# compiler* (as illustrated above in a diagram I pinched from Wikipedia) is a tool that translates C# code into bytecode known as [*MSIL*](https://en.wikipedia.org/wiki/MSIL).
89 |
90 | The *runtime* manages the execution of bytecode. It recognizes a set of [IL instructions](https://en.wikipedia.org/wiki/List_of_CIL_instructions) and translates them into machine-specific assembly instructions on the fly.
91 |
92 | The _framework libraries_ are essentially the libraries you reference from your projects to help you kick-start development:
93 |
94 | 
95 |
96 | They encompass primitive types like `Int32` and `String` as well as complex types like `HttpClient` etc.
97 |
98 | Understand that the new features in C# 6.0 stem from changes the compiler *only*. **You do *not* need to target the latest framework version to use C# 6.0 features.** This is because C# 6.0 is not dependent on new IL instructions, nor is it dependent on new types in the framework libraries (with one exception for *interpolated strings*, but we'll cross that bridge when we come to it.).
99 |
100 | One more thing to note before we dive in is that, if you want to use C# 6.0 (and of course, you do), you’ll need to be using Visual Studio 2015. If you are yet to install Visual Studio 2015, you can head over to the [Visual Studio website](https://www.visualstudio.com/en-us/products/vs-2015-product-editions.aspx), and download the community edition for free.
101 |
102 | ### Conclusion
103 |
104 | In this article I set the tone for C# 6.0. Now that you have a sound idea about what to expect, let's start by examining the first new feature: [expression-bodied members]().
105 |
106 | **P.S. If you read this far, you might want to follow me on [Twitter](https://twitter.com/bookercodes) and [GitHub](https://github.com/alexbooker), or [subscribe](https://booker.codes/rss/) to my blog.**
107 |
--------------------------------------------------------------------------------
/input-validation-in-express-with-express-validator.md:
--------------------------------------------------------------------------------
1 | Welcome to this short tutorial in which you'll learn how to validate form input in an Express app using an open-source Node module called [express-validator](https://github.com/ctavan/express-validator).
2 |
3 | ### Installation
4 |
5 | Installing express-validator is easy when you use [npm](https://docs.npmjs.com/getting-started/what-is-npm). Just input the following command:
6 |
7 | ```
8 | npm install express-validator
9 | ```
10 |
11 | This will download the latest version of the [express-validator npm package](https://www.npmjs.com/package/express-validator).
12 |
13 | Once the command has done executing - if you were to to look inside the _"node modules"_ folder, you'd see that express-validator has a transitive dependency on another module called [validator](https://github.com/chriso/validator.js):
14 |
15 | 
16 |
17 | You'll see why this is important later.
18 |
19 | ### Setup
20 |
21 | For the purposes of this tutorial, I'll assume you have a script whose contents look something like this:
22 |
23 | // dependencies
24 | var express = require('express');
25 | var bodyParser = require('body-parser');
26 |
27 | var app = express();
28 |
29 | // middleware
30 | app.use(bodyParser.urlencoded({ extended: false }));
31 |
32 | (If you don't, you can quickly create a application skeleton using the [application generator tool](http://expressjs.com/starter/generator.html).)
33 |
34 | express-validator is middleware which you can mount by calling [`app.use`](http://expressjs.com/4x/api.html#app.use):
35 |
36 |
37 | // dependencies
38 | var express = require('express');
39 | var bodyParser = require('body-parser');
40 | var validator = require('express-validator');
41 |
42 | var app = express();
43 |
44 | // middleware
45 | app.use(bodyParser.urlencoded({ extended: false }));
46 | app.use(validator());
47 |
48 |
49 | There is only one thing you need to watch out for and that is, you must `use` express-validator *after* you `use` the [body parser middleware](https://github.com/expressjs/body-parser). If you don't, express-validator will not work. This is because without the body parser middleware, it would not be possible to parse the values to validate.
50 |
51 | ### Validation
52 |
53 | In order to illustrate validation in action, we'll imagine that we have a request handler:
54 |
55 | app.post('/pages/create', function(req, res) {
56 | });
57 |
58 | And that the request body looks like this:
59 |
60 | {
61 | leader_email: "leader@something.edu",
62 | leader_mobile_no: "017171",
63 | team_twitter: "http://twitter.com/teamA",
64 | member_count: 10,
65 | page_color: "#FFFFFF",
66 | page_accent_colour: "#FFFFFF"
67 | }
68 |
69 | Here we want to validate that...
70 |
71 | - **leader_email** is a valid email address*
72 | - **leader\_mobile_no** is a valid UK mobile phone number
73 | - **team_twitter** is a valid Twitter handle
74 | - **member_count** is both a number and divisble by 2
75 | - **page\_color** and **page\_accent_color** are valid hex color codes
76 |
77 | *Remember. Validation is not the same as verification. Validation merely confirms that the email is in the correct format. Verification confirms that that the user has access to the email. If you need to verify the email, consider sending a verification email.
78 | 79 | Validating an email is a common requirement so we might as well start there. 80 | 81 | Inside of the request handler, make a call to the `req.checkBody` function. Pass to this function the name of the input you want to validate (in this case, _"leader\_email"_) and the error message you want to return if the input is invalid: 82 | 83 |
84 | app.post('/pages/create', function(req, res) {
85 | req.checkBody("leader_email", "Enter a valid email address.");
86 | });
87 |
88 |
89 | Next, tell the middleware which validators to apply by _chaining_ one or more validation functions:
90 |
91 |
92 | app.post('/pages/create', function(req, res) {
93 | req.checkBody("leader_email", "Enter a valid email address.").isEmail();
94 | });
95 |
96 |
97 | Hopefully now you can see why express-validator depending on [validator](https://github.com/chriso/validator.js) is not merely an implementation detail. You almost always end up calling functions from the validator library of validation functions. You can see a full list of validation functions [here](https://github.com/chriso/validator.js#validators).
98 |
99 | You might be wondering where exactly the `checkBody` function comes from. It comes from the express-parser middleware. Express middleware can add any property it wants to the `req` argument. In addition to the `checkBody` function, express-validator adds two more functions namely, `checkQuery` and `checkParams` which can be used to validate query parameters and route parameters respectively. See the [documentation](https://github.com/ctavan/express-validator/blob/master/README.md) for more information on those.
100 |
101 |
102 |
103 | For completeness, here is how I would validate the remaining input elements:
104 |
105 | ```
106 | req.checkBody("leader_email", "Enter a valid email address.").isEmail();
107 |
108 | req.checkBody(
109 | "leader_mobile_no",
110 | "Enter a valid UK phone number.").isMobilePhone("en-GB");
111 |
112 | req.checkBody(
113 | "team_twitter",
114 | "Enter a valid Twitter URL").optional().matches("http://twitter.com/*");
115 |
116 | req.checkBody(
117 | "contestant_count",
118 | "Contestant count must be a number and one that is divisible by 2"
119 | ).isNumber().isDivisibleBy(2);
120 |
121 | req.checkBody(
122 | "page_color",
123 | "Page colour must be a valid hex color"
124 | ).isHexColor();
125 |
126 | req.checkBody(
127 | "page_color_accent",
128 | "Page colour accent must be a valid hex color").isHexColor();
129 | ```
130 |
131 | Hopefully by now the above listing is intuitive. If you are unsure about what any of the functions do, you can refer to their descriptions [here](https://github.com/chriso/validator.js#validators). Aside from that, there are just a couple of things to note about this code:
132 |
133 | - In a couple of places we _chain_ more than one validation function. This is possible thanks to [_fluent interfaces_](https://en.wikipedia.org/wiki/Fluent_interface).
134 | - For the _"team twitter"_ input we chain the `optional` function before chaining the `matches` function. The `optional` functions says: _"this value is optional so do not attempt to validate it with `matches` **unless** the user actually entered something_". In other words, if the _"team twitter"_ input is empty, `matches` won't be called and the input will be deemed valid.
135 |
136 | Remember. All we've done so far is define some rules. We are yet to enforce these rules. We'll do that now.
137 |
138 | In order to determine whether the input is valid according to the rules, we call a function called `validationErrors`. If any input is invalid, this function returns an array of errors; otherwise - if all input is valid - it returns `undefined` (which indicates _"no errors"_). If the function returns an array of errors, we'll show them to the user:
139 |
140 |
141 | app.post('/pages/create', function(req, res) {
142 | req.checkBody("leader_email", "Enter a valid email address.").isEmail();
143 |
144 | var errors = req.validationErrors();
145 | if (errors) {
146 | res.send(errors);
147 | return;
148 | } else {
149 | // normal processing here
150 | }
151 | });
152 |
153 |
154 |
155 | 
156 |
157 | (As you may have noticed, I removed most validation rules from the request handler - this is solely for
158 | the sake of brevity.)
159 |
160 | Whilst emitting errors in JSON format might be appropriate for a web service, for most websites, this is not very nice. In such a case we can send `errors` back with a template:
161 |
162 |
163 | app.post('/pages/create', function(req, res) {
164 | req.checkBody("leader_email", "Enter a valid email address.").isEmail();
165 |
166 | var errors = req.validationErrors();
167 | if (errors) {
168 | res.render('create', { errors: errors });
169 | return;
170 | } else {
171 | // normal processing here
172 | }
173 | });
174 |
175 |
176 |
177 | And then in the template, show the errors conditionally:
178 |
179 | if errors
180 | ul
181 | for error in errors
182 | li!= error.msg
183 |
184 | 
185 |
186 | This is an example using the [Jade template engine](https://github.com/jadejs/jade). I know not everyone digs Jade so for good measure, here is another example, this time using the [Handlebars template engine](http://handlebarsjs.com/):
187 |
188 | {{ #if errors }}
189 |