Petal:...recated(3pm)

πŸ“¦
version 2.26 Β· 2 versions
  • 2.26 Β· debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking (latest)
  • 2.26 Β· ubuntu jammy
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

✨ NAME ✨

Petal::Deprecated β€” the lil doc that spills the tea on all the Petal syntax that's been deprecated. It's part of the User Contributed Perl Documentation collection, and yes bestie, it's (3pm). 🫢


πŸ’– IMPORTANT NOTE πŸ’–

Okay so first things first: this is an article, not a module. Not me, not a module, just a girl with opinions and a text file. πŸ™ˆ

Starting from version 2.00 onwards, Petal requires that you use well-formed XML. Periodt. This is because Petal now uses MKDoc::XML::TreeBuilder instead of HTML::TreeBuilder and XML::Parser. Glow-up era. ✨

In particular, this version of Petal CAN break backwards compatibility if you were using Petal's HTML mode with non-well-formed XHTML. Yeah. She said what she said. πŸ’€

If you still want to use broken XHTML, you can use Petal 2.00 together with Petal::Parser::HTB, which has been created for exactly this purpose. A whole module made just to hold your hand through the chaos, we love to see it. πŸŽ€


🌸 INLINE VARIABLES SYNTAX 🌸

<!--? This is a template comment.
      It will not appear in the output -->
<html xmlns:tal="http://purl.org/petal/1.0/">
  <body>
    This is the variable 'my_var' : ${my_var}.
  </body>
</html>

And if "my_var" contained Hello World, Petal would have outputted:

<html>
  <body>
    This is the variable 'my_var' : Hello World.
  </body>
</html>

Now let's say that "my_var" is a hash reference as follows:

$VAR1 = { hello_world => 'Hello, World' }

To output the same result, you would write:

This is the variable 'my_var' : ${my_var/hello_world}.

Slash notation, iconic, no notes. πŸ’…


πŸ‘‘ SETTING PETAL OPTIONS AS GLOBALS πŸ‘‘

If you want to use an option throughout your entire program and don't want to have to pass it to the constructor each time, you can set them globally. They will then act as defaults unless you override them in the constructor. Main character defaults, lowkey.

$Petal::BASE_DIR           (use base_dir option)
$Petal::INPUT              (use input option)
$Petal::OUTPUT             (use output option)
$Petal::TAINT              (use taint option)
$Petal::ERROR_ON_UNDEF_VAR (use error_on_undef_var option)
$Petal::DISK_CACHE         (use disk_cache option)
$Petal::MEMORY_CACHE       (use memory_cache option)
$Petal::MAX_INCLUDES       (use max_includes option)
$Petal::LANGUAGE           (use default_language option)
$Petal::DEBUG_DUMP         (use debug_dump option)
  # $Petal::ENCODE_CHARSET     (use encode_charset option) -- _DEPRECATED_
$Petal::DECODE_CHARSET     (use decode_charset option)

See that commented-out one? $Petal::ENCODE_CHARSET is _DEPRECATED_, don't be out here using it like it's 2009. 😭


🌈 TAL DIRECTIVES ALIASES 🌈

On top of all that, for people who are lazy at typing, the following aliases are provided (although I would recommend sticking to the defaults):

  • tal:define β€” tal:def, tal:set
  • tal:condition β€” tal:if
  • tal:repeat β€” tal:for, tal:loop, tal:foreach
  • tal:attributes β€” tal:att, tal:attr, tal:atts
  • tal:content β€” tal:inner
  • tal:replace β€” tal:outer

🚨 TRAP 🚨

Don't forget that the default prefix is "petal:" NOT "tal:", until you set the petal namespace in your HTML or XML document as follows:

<html xmlns:tal="http://purl.org/petal/1.0/">
Fr fr, this one gets everybody. The prefix is petal: until you declare that namespace, and then it's tal:. Read the line again. Read it twice. 🫢

πŸ¦‹ XINCLUDES πŸ¦‹

Let's say that your base directory is "/templates", and you're editing "/templates/hello/index.html".

From there you want to include "/templates/includes/header.html".

general syntax

You can use a subset of the XInclude syntax as follows:

<body xmlns:xi="http://www.w3.org/2001/XInclude">
  <xi:include href="/includes/header.html" />
</body>

For backwards compatibility reasons, you can omit the first slash, i.e.

<xi:include href="includes/header.html" />

relative paths

If you'd rather use a path which is relative to the template itself rather than the base directory, you can do it, but the path MUST start with a dot, i.e.

<xi:include href="../includes/header.html" />

<xi:include href="./subdirectory/foo.xml" />

etc.

limitations

The "href" parameter does not support URIs, no other tag than "xi:include" is supported, and no other directive than the "href" parameter is supported at the moment. Yeah, she's a minimal queen. ✨

Also note that contrarily to the XInclude specification, Petal DOES allow recursive includes up to $Petal::MAX_INCLUDES. This behavior is very useful when templating structures which fit well with recursive processing, such as trees, nested lists, etc. Go off, recursion. 🌳

You can ONLY use the following Petal directives with Xinclude tags:

  • on-error
  • define
  • condition
  • repeat

"replace", "content", "omit-tag" and "attributes" are NOT supported in conjunction with XIncludes. Sorry babe, them's the rules. πŸ’€


πŸ’… UGLY SYNTAX πŸ’…

For certain things which are not doable using TAL, you can use what I call the UGLY SYNTAX. The UGLY SYNTAX is UGLY, but it can be handy in some cases. Sometimes the ugly fit eats, sometimes it doesn't. 🀷

For example, consider that you have a list of strings:

$my_var = [ 'Foo', 'Bar', 'Baz' ];
$template->process (my_var => $my_var, buz => $buz);

And you want to display:

<title>Hello : Foo : Bar : Baz</title>

Which is not doable with TAL without making the XHTML invalid. With the UGLY SYNTAX you can do:

<title>Hello<?for name="string my_var"?> : <?var name="string"?><?end?></title>

Of course you can freely mix the UGLY SYNTAX with other Petal syntaxes. So:

<title><?for name="string my_var"?> $string <?end?></title>

Mind you, if you've managed to read the doc this far I must confess that writing:

<h1>$string</h1>

instead of:

<h1 tal:replace="string">Dummy</h1>

is UGLY too. I would recommend sticking with TAL wherever you can. But let's not disgress too much.

variables

Abstract

<?var name="EXPRESSION"?>

Example

<title><?var name="document/title"?></title>

Why?

Because if you don't have things which are replaced by real values in your template, it's probably a static page, not a template... :) πŸŽ€

if / else constructs

Usual stuff:

<?if name="user/is_birthay"?>
  Happy Birthday, $user/real_name!
<?else?>
  What?! It's not your birthday?
  A very merry unbirthday to you!
<?end?>

You can use "condition" instead of "if", and indeed you can use modifiers:

<?condition name="false:user/is_birthay"?>
  What?! It's not your birthday?
  A very merry unbirthday to you!
<?else?>
  Happy Birthday, $user/real_name!
<?end?>

Not much else to say! πŸ’–

loops

Use either "for", "foreach", "loop" or "repeat". They're all the same thing, which one you use is a matter of taste. Again, no surprise:

<h1>Listing of user logins</h1>
<ul>
  <?repeat name="user system/list_users"?>
    <li><?var name="user/login"?> :
        <?var name="user/real_name"?></li>
  <?end?>
</ul>

Variables are scoped inside loops so you don't risk erasing an existing "user" variable which would be outside the loop. The template engine also provides the following variables for you inside the loop:

<?repeat name="foo bar"?>
  <?var name="repeat/index"?>  - iteration number, starting at 0
  <?var name="repeat/number"?> - iteration number, starting at 1
  <?var name="repeat/start"?>  - is it the first iteration?
  <?var name="repeat/end"?>    - is it the last iteration?
  <?var name="repeat/inner"?>  - is it not the first and not the last iteration?
  <?var name="repeat/even"?>   - is the count even?
  <?var name="repeat/odd"?>    - is the count odd?
<?end?>

Again these variables are scoped, you can safely nest loops, ifs etc... as much as you like and everything should be fine. Nest away, bestie, the scoping has your back. 🫢

Includes

<?include file="include.xml"?>

It will include the file 'include.xml', using the current @Petal::BASE_DIR directory list.

If you want to use XML::Parser to include files, you should make sure that the included files are valid XML themselves... FYI XML::Parser chokes on this:

<p>foo</p>
<p>bar</p>

But this works:

<div>
  <p>foo</p>
  <p>bar</p>
</div>

(Having only one top element is part of the XML spec). One top element only, she's monogamous like that. πŸ’€βœ¨


That's the whole vibe check, bestie β€” written up from the User Contributed Perl Documentation, perl v5.36.0, dated 2022-11-19. Go forth, template responsibly, and remember: well-formed XML or nothing. πŸ’…πŸŒΈ

πŸ“¦ where this page comes from