Monday, May 23, 2011

Happstack + JMacro + HSX

Happstack (a Haskell web framework) has long had support for using HSX so that you can use XML syntax in your Haskell page templates. Happstack now has support for using JMacro to add javascript to your templates.

JMacro was written by Gershom Bazerman, and was first released in July of 2009. Our contribution is the creation of two glue libraries:
a thin wrapper which makes it easy to embed JMacro into HSX (independent of Happstack).
another thin wrapper that makes it easy to generate and serve JMacro .js scripts using Happstack

The use of Happstack+HSX+JMacro has been documented in detail in this section of the Happstack Crash Course.

Here is a little example of what Happstack+HSX+JMacro looks like:
> helloJMacro :: JMacroPart Response
> helloJMacro =
>     toResponse <$> defaultTemplate "Hello JMacro" ()
>       <div>
>        <% [$jmacro| 
>            var helloNode = document.createElement('h1');
>            helloNode.appendChild(document.createTextNode("Hello, JMacro!"));
>            document.body.appendChild(helloNode);
>            |] %>
>       </div>

As you can see, the syntax used by JMacro is almost identical to JavaScript. So, you do not have to learn some special DSL to use it. In fact, JMacro can work with most JavaScript you find in the wild. Using JMacro has a number of advantages over just using plain-old javascript:
  • syntax checking ensures that your JavaScript is syntactically valid at compile time. That eliminates many common JavaScript errors and reduces development time.
  • hygienic names and scoping automatically and transparently ensure that blocks of JavaScript code do not accidentally create variables and functions with conflicting names.
  • Antiquotation, marshalling, and shared scope make it easy to splice Haskell values into the JavaScript code. It also makes it easy to programmatically generate JavaScript code.

The last point means that instead of trying to concat strings to call JavaScript functions with Haskell values like this:
hello str = <button onclick=("alert(" ++ str ++ ");")>click me</button>

You can write:
hello str = <button onclick=[$jmacro| alert(`(str)`); |]>click me</button>

The first version has a major bug -- it does not properly escape the str which can lead to javascript injection attacks. The JMacro version, on the other hand, automatically escapes the string.

You are not limited to just splicing strings and other primitive types into the JavaScript code. By creating an instance of ToJExpr you can easily pass any Haskell value to JavaScript.

While JMacro can easily be used for simple templating, it is actually a very powerful tool for generating JavaScript. It is essentially Template Haskell for JavaScript. It parses the JavaScript into an abstract syntax tree, and supports quasiquotation and antiquotation.

To learn more about using JMacro with Happstack and HSX, start reading here.

And a big thanks for Gershom Bazerman for creating JMacro. It's not part of Happstack or HSX, so you should have no problems using it with other web frameworks or templating libraries.

No comments:

Post a Comment