SYNOPSIS

I've been working on a set of modules for a couple of weeks now based on 
work I've been doing with several web page authors and copywriters.

I created a module named Text::UberText which is designed to be a 
lightweight template system with the ability to be extended easily with 
third party code.

Text::UberText was designed meet several needs.

1. Create a template language specification that was easy to read and write.  
People using the language should not be required to have strong programming 
skills.

2. The template language should not follow Perl syntax rules, or be designed 
with preference towards Perl users or programmers.  It should also not 
be used as a system to simply merge perl code in a document.

3. The parser needs to have a simple interface for module authors to add 
their own code without requiring extensive rewrites of an existing 
codebase.

4. The parser needs to understand the order and structure of the document 
data.  The information needs to be made available to programmers writing 
code to interact with the parser.

5. The template language should use multiple namespaces, so object code 
using the system don't create overlapping commands.  For example, if two 
different objects created a tag named "address", the parser should 
understand which object the tag is associated with.

OTHER TEMPLATE PARSERS

Searching under the "Text" namespace alone reveals at least four different 
template parsing systems.  There are also parsers under "Apache", 
"HTML", and a top level namespace called "Template".  The high number of
submissions is partially what lead to the need for a unique named like
"Text::UberText".

Given the high number of template systems out there, it is easy to understand 
the reluctance or hesitation in adding another one to CPAN.  But I would 
like to briefly cover some of the other systems out there.  It is not 
my intention to criticize other works, but to discuss why I felt these 
systems didn't meet all of the requirements I wanted.

1. Text::FillIn, Text::SimpleText, Text::Template

Each of these systems work on the principle of simple variable 
substitution.  The example documents listed show perl syntax embedded in 
the source templates to reference variables, or in one example, perl 
subroutines.  The features are too limited for complex documents.

2. Text::MetaText

MetaText uses a simple set of commands to generate documents, like INCLUDE, 
and DEFINE.  It is a good tool for merging multiple documents, or variable 
substritution, but it has a very limited command set with no means
to allow for expansion.

3. Text::Templar

Text::Templar allows for template designers to create subroutines that 
are called from the template parser.  However, it only maps methods of 
the Templar object itself, which limits the ability to add more 
method calls.

4. HTML::Mason, Text::MicroMason

Mason allows document writers to include large chunks of perl code in 
documents that is evaluated, and the result of that code is replaced 
in the document.  It's very flexible, but it relies on document writers 
to be Perl programmers, or have an understanding of perl.

5. Template Toolkit

The closest match to Text::UberText is the Template Toolkit.  It allows 
for template commands to be matched against variables or subroutines, 
and it has a large plug-in library which indicates that it is 
easy to expand.  

EXAMPLE DOCUMENT

The following is very simple document that can be read by Text::UberText

>
>Today is [uber.time date format:(mm/yy/dd)].
>
>[uber.var name:(user) value:([unix.env var:(USER)])]
>Your username is [uber.var name:(user)].
>
>The ball is [uber.var name:(color)] and [uber.var name:(size)] 
>inches in diameter.
>

Other examples are listed in the POD documentation below.

HOW THE DOCUMENT IS PARSED

The command structure is refered to as a command tag.  It contains a 
namespace which points to an instantiated perl module, and commands 
with additional options and values passed to options.

Like HTML or XML, it also allows for command tags to act as containers 
for document text or other commands.

When the source data is read, it is parsed and broken down into a tree 
structure.  When the parsing method is explicitly called, the command tags 
are examined, and the appropriate method calls are made depending on 
the namespace and the command in the tag.  The output is then saved and 
returned back to the caller when requested.

Comments and criticism welcome.  Below is the POD documentation for the 
main module.  The code is still in beta, but it's relatively stable and 
could probably be uploaded to CPAN within a week.


----------------------------------------

NAME
    Text::UberText - Customizable Template Engine

SYNOPSIS
     use Text::UberText qw(standard);

     $ub=Text::UberText->new();
     $ub->read(@array);
     $ub->extend($acme_invoice);
     $doctree=$ub->parse();
     if ($doctree)
     {
         $doctree->run();
         print($doctree->output());
     }

DESCRIPTION
    Text::UberText is an expandable template system designed to let
    programmers write their own commands and tie those commands to
    program code. UberText reads command tags in documents, and then
    calls perl modules based on the tag.

SAMPLE DOCUMENT
    The following is an example of a document that uses the UberText
    template system.

     Invoice#: [uber.print string:([acme.invoice number]) fmt:(%010d)]
     Date:     [uber.date date fmt:(MM/DD/YYYY)]

     Ship To: [acme.invoice address:(shipping) ]

     Tracking number: [acme.invoice tracking-number vendor:(ups)]

     [acme.invoice itemlist -> ]
      Item: [acme.invoice itemnumber] [acme.invoice description]
     [<- acme.invoice itemlist ]

     [acme.invoice terms]

    The template is designed by a programmer that has designated the
    "acme.invoice" namespace is to be used for his code. He then
    writes Perl modules that interface with Text::UberText when the
    document is parsed.

UBERTEXT FORMAT
    UberText documents are plain text mixed with command tags. A
    very simple command tag contains a namespace and a command.

     [uber.info version]

    In this case, the namespace is `uber.info' and the command is
    `version'.

    Commands can have values passed to them.

     [uber.info version:"full"]

    Commands can also have additional options, and those options can
    have values.

     [uber.var name:(variable) value:"This is the value of the variable"]

    Values for commands or options are specified by following the
    command or options with a colon, and then enclosing the value in
    paranthesis or double quotes.

    An UberText command can also be wrapped around portions of text
    or other UberText commands. These are considered block commands.

     [uber.transform indent class:(quote) ->]
       "You can reach be anytime at my work number [per.info phonenum:(work)]"
     [<- uber.transform ]

    Command options can be placed in either the tag that starts the
    block, or the tag that ends the block. This example....

     [uber.loop count:(20) -> ]
       This text will repeat 10 times
     [<- uber.loop start:(11) ]

    Is identical to..... [uber.loop count:(20) start:(11) -> ] This
    text will repeat 10 times [<- uber.loop ]

    You can also insert UberText commands in the values of options
    or commands.

     [uber.var name:(version) value:([uber.info version])]

     [uber.print string:(The fruit is [uber.rand words:(orange,apple,banana)]) ]

    But you cannot use block commands inside the values to options
    or commands.

    UberText command tags can span multiple lines.

     [
            uber.var name:(customer) 
                    value : "John Q. Public"
     ]

    Leading and trailing whitespace within an UberText command is
    eliminated. Some whitespace is needed to seperate the namespace,
    the command and options, but that's it. Whitespace within values
    to commands and options is kept intact. Also, whitespace after
    the command tag (including carriage returns) is kept intact as
    well.

LOADING
    UberText comes with a set of modules handling a small set of
    basic functions. All of the modules are in the
    Text::UberText::Modules Perl namespace. You can specify which of
    those modules are loaded on the use line.

     use Text::UberText qw(minimal);

    The modules are not actually loaded until an UberText object is
    initiated.

    The following is a list of module sets.

    none
        None of the included UberText modules are loaded.

    minimal
        Only the Text::UberText::Modules::Info module is loaded

    standard
        The modules Text::UberText::Modules::(Info,Version) are
        loaded.

METHODS
    $ubt=Text::UberText->new();
        Creates a new UberText object. The parser, the dispatch
        table, and the log are all initialized.

    $ubt->read(@input);
        Reads in the passed array and passes it to the parser.

    $tree=$ubt->parse();
        Runs the parser against the input. At this time, the
        commands and the document text are sorted out and placed in
        a Text::UberText::Tree object, which keeps track of the
        document. The tree object is then returned from the method
        call.

    $ubt->extend($object);
        Sends an object to the Text::UberText::Dispatch object,
        which controls all methods that interface with the command
        nodes. $object is either a Perl object, or just the name of
        a class. In either case, the Dispatch object searches for a
        method called `uberText' and runs it. It then takes data
        returned from the call and uses it to expand its internal
        dispatch table.

BUGS/CAVEATS
    UberText is pretty complex. There's probably bugs floating
    around because I haven't even conceived of all of the possible
    input errors or third party module errors that it needs to deal
    with.

AUTHOR
    Chris Josephes <[EMAIL PROTECTED]>

SEE ALSO
    the Text::UberText::Tree manpage, the Text::UberText::Dispatch
    manpage, the Text::UberText::Parser manpage

COPYRIGHT
    Copyright 2002, Chris Josephes. All rights reserved. This module
    is free software. It may be used, redistributed, and/or modified
    under the same terms as Perl itself.

--------------------
Christopher Josephes 
[EMAIL PROTECTED]

Reply via email to