=pod I released the first version of C today. C is my attempt to resolve the eternal conflict between developers and web designers. I'm sure you've heard of this problem before. A developer and web designer want to work on a project together. The web designer only knows HTML, not programming. The developer only knows programming, not design. This is a problem, because often times both things need to be in the same file. Templating systems usually try to make the programming part easy for the designer to avoid while still allowing the programmer some flexibility in controlling the page rendering. Unfortunately, the balance never seems to be quite right -- if the programmer abstracts too much away, the designer won't know which file to edit and won't be able to see her changes in the browser unless she has an instance of the application running. So although current templating systems try to make things easy for both the designer and the programmer, they usually make things easy for the programmer and hard for the designer. They were all written by programmers, after all. :) I decided to solve this problem by writing a templating system that's easy for designers I programmers. Instead of demanding that the designer learn to code (as with C or C) or that the programmer dumb his code way down (like C or Clearsilver), I let the designer produce HTML and the programmer produce Perl to I that HTML into a final product. No more compromises! The designer only has to deal with HTML; HTML that is viewable in a browser with no additional effort. The coder can easily write complex code (and test that code easily) without the designer caring at all. Perfect! (BTW, I don't claim to have invented this idea. XSLT and C are prior art.) Anyway, enough hype. Let's see how it works. We'll start with a very simple task -- variable interpolation. In C, we look at document regions, not "control structures", so the input HTML can look like anything. The designer doesn't need to specifically mention in the template where C<$foo> is being interpolated. In reality, the designer is probably going to give you a page with some test data where the interpolation should be, like this: lang:HTML

Hello, world.

The C class is there because the designer always wants usernames to show up in a yellow-on-green font, but we can use this tag to know where to interpolate the C<$username> variable. So let's do that. We start by loading C. The main entry point is currently C. This class represents a document fragment that can be refined. lang:Perl use Template::Refine::Fragment; use Template::Refine::Utils qw(simple_replace replace_text); We also load some sugar, C. Continuing, we need to load the document: my $frag = Template::Refine::Fragment->new_from_file('welcome.html'); Here we load the contents of C; you could also load from a string with the C constructor. (An C DOM tree is another option; see the POD for details.) Now we need to write the rule to replace the test data with the real username in the right places. C contains a function, C, that will return a C object to do this. (It covers up a verbose-but-complete API for writing rules. You can read the POD or source if you want to know how the whole rule processing system works.) C takes two arguments, a coderef that generates the replacement DOM node given the current DOM node, and an XPath expression that finds relevant DOM nodes. In this case, we want to find nodes that look like C. The code we want to run on each of those nodes will remove all the text inside the node and replace it with the username: sub { my $node = shift; return replace_text $node, $username; } C is another utility function. It will take C<$node>, make a copy, remove the copy's children, add a simple text node (using C<$username> as the text) as a child, and then return the whole thing. This has the effect of transforming a node like C<<

Hello, world

>> to C<<

Your text goes here

>>, which is what we want to do here. (You can build your own nodes with the C API if you want.) Anyway, the whole rule will look like this: my $username = 'Test User'; my $rule = simple_replace { my $node = shift; return replace_text $node, $username; } '//*[@class="username"]'; Once we have the rule, we just need to apply it to the document fragment C<$frag>: $frag = $frag->process($rule); We assign the result of the process call to the original variable since C returns a copy; it doesn't modify the original document. I was in a functional-programming mood when I wrote the module. (Copying minimizes confusing side-effects, anyway.) We can obviously call C<$process> as many times as we want. When we are done processing, we just need to C the document to get our HTML back: say $frag->render; That will then print: lang:HTML

Hello, Test User.

And that's that. The basic flow is: lang:Perl Template::Refine::Fragment-> new( ... )-> process( simple_replace { ... } '//x/path' )-> render; Simple! (BTW, in case you're wondering how it's possible to apply XPath expressions to document fragments and where C is, we reparent the fragment inside C<< ... >>, yielding a full XML document. So C is the C node, and everything works.) Let's do one more example -- this time, a bit more complicated. This is another situation I'm sure you've encountered. You have a form, and some fields are required. You want to annotate the labels of the required fields with a C<*> so that the user knows they're required. (You also don't want the designer to do this manually, since you may change the requirements in your code at some point.) C to the rescue! We'll start by defining a Moose class that is the "result" of submitting the form: package Person; use Moose; has 'name' => ( is => 'ro', isa => 'Str', required => 1 ); has 'bio' => ( is => 'ro', isa => 'Str' ); has 'age' => ( is => 'ro', isa => 'Int', required => 1 ); Hopefully you're using Moose by now, but if not, I think the code is pretty easy to understand. Person has three fields, name, bio, and age. Name and age are required. Bio is optional. Now let's see what the designer gave us as HTML: lang:HTML
Name:
Biography:
Age:
You can see that each field has a region that can be selected with C<< //div[@id=''] >>. Inside that region, the label can be selected with C<< //span[@class='label'] >> or similar. Here's how to write a C rule for a two-stage scheme like this: lang:Perl sub transform { my $frag = shift; for my $attribute (Person->meta->compute_all_applicable_attributes) { my $attribute_id = $attribute->name; $frag = $frag->process( simple_replace { my $n = shift; my $sub_fragment = Template::Refine::Fragment->new_from_string( $n->toString, ); return annotate_required_field($sub_fragment, $attribute)->fragment; } "//*[\@id='$attribute_id']" ); } return $frag } sub annotate_required_field { my ($fragment, $attribute) = @_; return $fragment unless $attribute->is_required; return $fragment->process( simple_replace { my $n = shift; return replace_text $n, $n->textContent . ' *'; } q|//*[@class='label']|, ); } The C subroutine processes the entire form. For each attribute, it creates a rule that finds that attribute's region (the div). In the coderef that generates the replacement, we generate a C that represents only that region. Then we process the "sub fragment", this time looking for the labels (via C). For each label found, we get the existing text and add a C<*> if the attribute's metaclass indicates that it is required. The whole script (minus those two functions) looks like this: use Person; use Template::Refine::Fragment; use Template::Refine::Utils qw(replace_text simple_replace); my $frag = Template::Refine::Fragment->new_from_file('person_form.html'); print transform($frag)->render; And the output is what you would expect from looking at the HTML and Moose class: lang:HTML
Name *:
Biography:
Age *:
I think this is pretty cool. If you change the Moose class, the HTML changes. But the designer doesn't need to know code, and you don't need to know design! It Just Works. Yay! I see a lot of applications for this. One that sounds interesting but I haven't tried yes is document localization. You can read the document in, find the area to translate (via xpath), look up the existing text in the English to msgid conversion table, find the string for the language you are looking for, and replace the English with the language you are translating in to. This means you can maintain your HTML in (mostly) English, and translate "out of band". It seems like it could work. (If you want more applications, look in my C repository. I am using C for interfacing Moose and HTML.) An interesting side-effect of using C is that you have an introspectable DOM for all of your HTML. In times past, HTML was just some garbage that your app passed to the browser in hopes that it would understand it. Now your program actually understands the HTML, and can do intelligent things with it. For example, you will know immediately when your HTML is invalid (and C can't auto-fix it); the C constructor will die. You can find all "p" nodes and spell-check them. You can pretty-print the HTML for development, but compress it for production. The list goes on -- I think this is a pretty major change in how applications treat HTML. (Of course, everyone using XSLT has known this for a long time.) Anyway, C is a very simple module, so don't hesitate to try it out, read the code, and improve it! I think it's a nice compliment to other templating systems (you don't have to use it for everything), and it has a very high usefulness-to-complexity ratio -- C is 400 lines of code, including docs. Template Toolkit is 26,000 lines! Have fun.