Posts

Showing posts with the label heist

Splice Subtleties

In the recent release of Heist 0.5.1, there was performance bug in my implementation of head merging. I turned off the head merging, and then fixed the bug but did not reenable head merging. If you want to turn it back on, you need to bind the html tag to the htmlImpl function from the Text.Templating.Heist.Splices.Html module. I think I'll continue to leave it off by default because it does have some potential to impact performance.

While analyzing the problem, I realized that it involves fairly obscure details of Heist internals that have not been mentioned in any of our tutorial materials. And if I, the original author of Heist fell prey to this problem, it's probably safe to assume that eventually someone else will too. So let's take a look at some details of Heist's internal behavior and the implications for splice developers.

As I alluded to in Heist in 60 Seconds, you can think of a splice as follows:

type Splice = Node -> m [Node]

The actual implementati…

Heist Template Abstractions in a Nutshell

In the last post I discussed how logic and control flow can (and I argue should) be done in splices where types, higher order functions, and the full power of Haskell can be applied to the problem. In this post I want to take some time to think about the raw materials that are available in templates.

At the lowest level, we have just Text (...which is certainly /= Nothing). The templates are read in as Text and parsed into HTML DOM structures: elements, children, and attributes. Heist's abstractions for these entities are roughly analogous to the lambda calculus. The lambda calculus primitives are function definition and function application. HTML structures don't have any kind of representation for functions, so Heist uses lists of DOM tree nodes as the fundamental unit. Two different ways of representing them are splices and templates. The following table summarizes Heist's HTML abstraction tools.

DefinitionApplication
/EvaluationSplices<bind>use the tagTempla…

Looping and Control Flow in Heist

One of the most frequent questions I get about Heist is how to do loops or control flow in Heist templates. I usually respond that we've tried to avoid introducing these constructs into templates to encourage a better separation between view and model/controller. In this post I want to discuss the issue in more detail so that my thoughts are stored and I can refer people here in the future.

Since Haskell is pure and has a strong static type system, the first thing to think about when discussing this question is what types will be involved. Since templates are processed at runtime, they do not have access to Haskell's type system. This puts us square in the middle of byte-land. No generalized looping over things like the list of registered users or recent posts. No type-safe evaluation of arbitrary expressions. It is my contention that you're better off solving these problems with a language designed for that purpose...i.e. in Haskell splices, and not in HTML templat…

Views, Controllers, and Heist

A very common question when using Heist is how to specify views in a splice. There are three different approaches one can take:

1. Specify a splice's view in the Haskell code implementing the splice.
2. Get a splice's view from a template.
3. Pass the desired view to the splice as the spliced tag's child nodes.

Aproach #1 tends to be ugly and violates the principle of separating logic and view.  There are always exceptions to every rule, so we've done a little bit to ease the implementation of #1 by allowing xmlhtml DOM structures to be built with blaze-html syntax.  However, I believe that one of the other approaches will usually be preferable.

Approach #2 seems kind of awkward.  It would result in a whole bunch of small templates on disk that define little pieces of web pages.  An architecture like this might be desireable in some situations as a way to eliminate repetition (and it certainly fits into the functional programming mentality of lots of small functions),…

Heist in 60 Seconds

A template system is a bridge between static data (templates) and dynamic data.

Heist is a template system bridging HTML templates and Haskell code.

A splice is code that Heist binds to an HTML tag.

Every time the tag appears in a template, Heist runs the splice bound to that tag and passes the tag (including its attributes and its children) as input to the splice.

A splice's output is a list of tags that get substituted into the template in place of the original input tag.

Splices can be thought of as functions that can be called from templates to get dynamic data.

Splices can pass this dynamic data back to templates by (temporarily) binding new splices.

<bind> is a tag you can use in your templates to create new splices on the fly.

<apply> is a tag that lets you insert one template into another.


A more in-depth tutorial is here.

Heist Gets Blaze Syntax

Update: Heist has switched from using hexpat to using xmlhtml as of version 0.5. You can still use blaze syntax as described in this post, but you have to import Text.Blaze.Renderer.XmlHtml instead.

Users of Heist, my Haskell templating system, got a very nice surprise for Christmas this year when Jasper Van der Jeugt uploaded a new package blaze-html-hexpat to Hackage. If you're not familiar with Heist, you should probably check out the tutorial before reading further. Heist uses the Haskell XML library hexpat for XML template parsing and internal representation. Users are encouraged to put as much markup as possible into templates and keep Haskell-generated markup to a minimum. However, it is impractical to do this 100% of the time.

When the situation arises where you do want to generate bits of markup in code, you have to generate hexpat data structures.  Hexpat does provide some convenience functions for this purpose (see the Tree and NodeClass modules), but most would ag…

Heist 0.2 Released

Yesterday I released version 0.2 of the Heist XML templating library. This release makes some significant API changes, so it may break existing applications. But if you're only using Heist for basic templating, then you probably won't have to change anything. However, http://snapframework.com uses Heist extensively; and it did not require any code changes to upgrade. Here is a summary of what changed in 0.2: String substitution in attributesSupport for DOCTYPE in templatesNew implementation for TemplateMonadWindows supportTypeable instanceDocumentation improvementsBug fixesThe biggest new feature in 0.2 is attribute string substitution. Because Heist's templating mechanism uses XML tags, it didn't automatically work for string substitution inside tag attributes. You don't have to do very much web development before you find yourself wanting this. Now you can get substitution in attributes using the syntax "$(name)". The Heist Tutorial describes th…