in reply to RFC: Templating without a System

Using comments to hide templating stuff is pretty cruddy. If you need to stick values in attributes, you’ll be writing invalid markup, which HTML editing tools that don’t know your template syntax will complain about. And if you have loops building the output, it’s likely that the markup around those areas will be both invalid as well as very different from the final output. Even if the markup were perfectly sensible, there’s no default content in your template, so if it is rendered unprocessed the result will make little sense. Also, it looks as though you make no attempt to HTML-escape anything, so if you use your system on a public site you’ll have to spend a lot of effort making very sure it’s not vulnerable to cross-site scripting attacks.

The best templating system I have found is Petal, an implementation of TAL, which addresses all of these points by keeping template-related stuff in special attributes. (Actually, Kid is better yet, with a TAL-inspired but better syntax – but it’s a Python lib, not a Perl module.)

I haven’t looked at the implementation in much detail (only at your example template and output) because there is way too much in there for a templating system that’s supposed to be simple. You appear to be mixing together concerns wildly instead of separating them.

Makeshifts last the longest.

Replies are listed 'Best First'.
Re^2: RFC: Templating without a System
by shmem (Chancellor) on Jul 25, 2006 at 00:15 UTC
    Hmm. Please explain why stuffing templating stuff into comments is cruddy to your view. I used that approach because comments are ignored by browsers, and sensible behaving editors don't mess them up. Of course, if I have an odd number of, say, $foo-- occurrences, I break the rules, but other than that comments are just fine. Pages look for me way more ugly if a browser displays [% foo.bar %] or <TMPL_VAR baz>, which really break design.

    But for loops and stuff - I had all that nicely stuffed into comments, and yes, I had default content marked up with <!-- perl dummy -->default stuff here<!-- perl dumy end --> which are entirely weeded out.

    The only places where perl variables shine through is in, yes, attributes, which having invalid values distort the output; and in content /values of form elements.

    I solved that with a bunch of regexes to insert the perl stubs during the function generation; indeed using a real html/xml parser would be much better and less error prone.

    Next, HTML-escaping is not the templating engine's business, but of the caller which validates input and provides content anyways - it should be done there.

    Petal? I've looked at it; it's an approach with full xml / html validation as is HTML::Seamstress, and there's too much overhead in it. Doing the same tasks over and over again, as I understand them. And the special attribute syntax is -- well, special, and too little perl related to my liking.

    The bunch of code I published in this thread is lousy and buggy, and I'm cleaning that up. Have you read the follow-up? I think there I've laid out my ideas more precisely, and I'll have it all made into a module by the end of this week. I appreciate your comments and would be glad if you had a look at it.

    greetings,
    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}

      The point is, you can just as well hide directives in special attributes, and then you’re guaranteed not to break HTML syntax rules and you can provide default content without the massive verbosity of bracketing it with special comments on both sides.

      HTML-escaping is definitely the engine’s business. Why do you think are cross-site scripting attacks so common? Because everyone eventually forgets to escape something; or is just lazy. But only a vanishing minority of cases ever requires output to be printed unescaped. Good defensive programming sense then demands that escaping should be the default.

      As for Petal and others doing the same tasks over and over, how is that relevant? You don’t have to choose to follow their implementation if you follow their language design.

      Makeshifts last the longest.

        Hiding directives in special attributes is a good thing, but that only holds for variable expansion, not for control structures. These are - for any template's native language - best done in what comments are for that language, imho. For HTML, that's <!-- -->; for PostScript, that's %% at the beginning of a line, and so on.
        HTML-escaping is definitely the engines business. Why do you think are cross-site scripting attacks so common? Because everyone eventually forgets to escape something; or is just lazy. But only a vanishing minority of cases ever requires output to be printed unescaped. Good defensive programming sense then demands that escaping should be the default.

        No, it's not. While HTML-escaping is necessary and MUST be done, it's not the templating engine's business. Processing templates is about output, and stuff that could lead to cross-site-scripting attacks comes in via input.

        If unsafe content makes it's way through a program right to the last stage of processing before outputting a page, or if it produces insecure content from other sources, I'd consider that program to be seriously broken. I'm definitely not condoning forgetfulness or the wrong type of laziness by providing safety nets for lousy acrobats. Rather, I'd give them enough rope to hang themselves three times, and probably a nice explosive fuse rope.

        As for Petal and others doing the same tasks over and over, how is that relevant? You don't have to choose to follow their implementation if you follow their language design.
        Good point. That's what I'm currently doing, so... delivery postponed ;-)

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}