=head1 NAME

Web::XDO -- static web site tool

=head1 SYNOPSIS

 #!/usr/bin/perl -wT
 use strict;
 use Web::XDO;
 
 # variables
 my ($xdo);
 
 # get XDO object
 $xdo = Web::XDO->new();
 
 # custom configurations here
 
 # output XDO page
 $xdo->output();

=head1 DESCRIPTION

XDO ("extensible document objects") is a tool for creating simple static web
sites.  Full documentation for XDO is in the
L<official web site|http://www.idocs.com/xdo/>. This POD documentation focuses
on the internals of Web::XDO.

=head1 INSTALLATION

The module Web::XDO can be installed with the usual routine:

 perl Makefile.PL
 make
 make test
 make install

After you install Web::XDO you should check out the
L<online installation guide|http://idocs.com/xdo/guides/version-0-10/install/>
for the remaining steps.

=head1 OVERVIEW

Web::XDO is called from a Perl CGI script that you write. The script should
look something like this:

 #!/usr/bin/perl -wT
 use strict;
 use Web::XDO;
 
 # variables
 my ($xdo);
 
 # get XDO object
 $xdo = Web::XDO->new();
 
 # custom configurations here
 
 # output XDO page
 $xdo->output();

The $xdo object does all the work or creating a CGI object, parsing and
processing the contents of the .xdo page, and outputing the results.  This POD
page documents thos internals.

=head1 CLASSES

=head2 Web::XDO

=head3 Web::XDO->new()

Web::XDO->new() creates a new Web::XDO object. It takes no parameters or
options.

 # get XDO object
 $xdo = Web::XDO->new();

=head3 $xdo->initial_tag_defs()

initial_tag_defs() is a private method that defines the default behavior of
XDO and HTML tags.  In subsequent releases the hash of tag definitions will be
configurable.

=head3 $xdo->output()

output() outputs the requested XDO page. It take no params or options.

=head3 $xdo->show_src()

show_src() is a private method that handles showing the XDO code when the
L<src URL parameter|http://idocs.com/xdo/guides/version-0-10/configuration/src-param/>
is sent.

=head3 $xdo->xdo_significant_tag($token)

xdo_significant_tag() is a private method that returns true if the given token
is specially processed by XDO, as opposed to output as-is for tags that aren't
significant. So, for example, an
L<< E<lt>includedE<gt>|/Web::XDO::Token::Tag::Include >> tag is significant, but the
E<lt>i<gt> tag is not.

=head3 $xdo->page_class()

page_class() returns the class name for an object representing an XDO page.
Right now page_class() always returns Web::XDO::Page. In susequent releases
this method will allow coders to create custom classes for different types
of pages. I haven't worked out the details on how that's going to work.

=head3 $xdo->default_tag_class()

default_tag_class() returns the tag class used for tags that are not recognized
by XDO. In subsequent releases programmers will be able to override Web::XDO
and have this method return their own custom tag class.

=head3 $xdo->status_404()

status_404() outputs a "404 Not Found" page and exits.  This method is called
when the requested XDO page is not found.

=head3 $xdo->adjust_url_for_root($url)

adjust_url_for_root() is an internal method that removes
L<< E<lt>xdo-rootE<gt>|/Web::XDO::Token::Tag::XdoRoot >>
from the beginning of a URL and substitutes in the value of
L<< $xdo-E<gt>{'root'}|http://idocs.com/xdo/guides/version-0-10/configuration/xdo-root/ >>.
Care is taken in this method to ensure that a single / is put between
E<lt>xdo-rootE<gt> and whatever comes after it.

=head3 $xdo->tag_class()

tag_class() is an internal method for determining the class name for a given
tag name.  If the tag is defined in
L<< $xdo-E<gt>{'tags'}|/$xdo-E<gt>initial_tag_defs() >>
then that name is returned,
otherwise the value of
L<< $xdo-E<gt>default_tag_class()|/$xdo-E<gt>default_tag_class() >>
is returned.

In subsequent programmers will be able to superclass Web::XDO and override
this method to use their own routines for determining tag class.

=head2 Web::XDO::Page

A Web::XDO::Page object represents a single XDO file.  When an XDO page is
requested, the corresponding XDO file is parsed into a Web::XDO::Page
object.  Each page that object includes is itself parsed into a Web::XDO::Page
object.

Web::XDO::Page superclasses
L<HTML::Parser|http://search.cpan.org/dist/HTML-Parser/Parser.pm>.  The XDO
file is parsed as part of Web::XDO::Page-E<gt>new().

=head3 Web::XDO::Page->new()

Web::XDO::Page->new() takes four parameters plus one optional parameter:

=over 1

=item *

$class: The name of the page class. For this release it's always
"Web::XDO::Page".

=item *

$url_root: The base page against which an absoulte URL path should be
calculated from $url_rel_path.  Yes, this variable should actually be called
$url_base.  That will be fixed in subsequent releases.

=item *

$url_rel_path: The relative URL path from $url_root.

=item *

$xdo: The Web::XDO object that is handling the entire process.

=item *

caller=>$page

If a page is being included in another page then the included page needs to
know its "caller" page.  That information is set with the caller option. So,
for example, the L<< E<lt>includedE<gt>|/Web::XDO::Token::Tag::Include >> tag
creates the included page object with a call like this:

 $included = $xdo->page_class->new($url_base, $atts->{'src'}, $xdo, 'caller'=>$caller);

If a caller is sent then that object is stored in the included page in the
$page->{'caller'} property.

=back

=head3 $page->top()

This method returns the top page in the hierarchy of included pages. If a
Web::XDO::Page object is created with the 'caller' option (which means the
caller page is stored in $page->{'caller'}), then the page's caller's
top() method is called and returned.  The top() method is called recursively
up the hierarchy until the top page (which has no caller) is reached. The top
page returns itself and that result is returned back down the hierarchy to page
that initiated the routine.

=head3 $page->top_props()

Returns the top page's {'props'} hash. Only the top page should have a
{'props'} hash and only properties in that hash should be set.

=head3 $page->set_paths($url_root, $url_rel_path)

This internal method sets the page's url_path property to an absolute path.
The absolute path is calculated using the $url_root and $url_rel_path
params. The final result is put into the $page-E<gt>{'url_path'}.

I<Note:> I put a lot of effort into addressing attempts to read files outside
the document root.  A particular concern is for someone to send a request
directly to xdo.pl with something like this:

 xdo.pl?p=../../../../../etc/passwd

If set_paths() doesn't properly filter the request then such a request could
return unauthorized files.

=head3 $page->output()

output() outputs the page.

=head3 $page->start()

Web::XDO::Page superclasses
L<HTML::Parser|http://search.cpan.org/dist/HTML-Parser/Parser.pm>.
start() handles HTML::Parser's event when a start tag is parsed.

start() creates a new tag object using the class returned by
L<< $xdo-E<gt>tag_class()|/$xdo-E<gt>tag_class() >>.

=head3 $page->end()

end() handles HTML::Parser's event when an end tag is parsed.
end() creates a new end tag object with the
Web::XDO::Token::EndTag class.

=head3 $page->text()

text() handles HTML::Parser's event when an end tag is parsed.
text() creates a new text object with the
Web::XDO::Token::Text class.

=head3 $page->is_directory_index()

is_directory_index() returns true if the XDO page is a
L<directory index|http://httpd.apache.org/docs/2.2/mod/mod_dir.html#directoryindex>
file.  Generally you should
L<configure your server|http://idocs.com/xdo/guides/version-0-10/install/configure-web-server.xdo>
so that the directory index file is named index.xdo.

=head3 $page->url_path_sans_directory_index()

This method returns the $page->{'url_path'} property with the name of the
directory index file removed.  If the page is not a directory index file then
the path isn't changed.  So, for example, this url_path

 /mysite/index.xdo

would be return as /mysite/, whereas this url_path

 /mysite/resume.xdo

would be returned as /mysite/resume.xdo.

=head3 $page->title()

This method returns the title of the page as set with the
L<< E<lt>propertyE<gt>|/Web::XDO::Token::Tag::Property >> tag. The tag should
have the name attribute set to "title", like this:

 <property name="title" value="My Home Page">

If the path option is sent, and if a property of path-title is set, then
path-title will be returned.  The path-title is used with the
L<< E<lt>pathE<gt>|/Web::XDO::Token::Tag::Path >> tag. So, for example, suppose
you want the title of your home page to be "My Home Page" when the page itself
is displayed, but just "Home" for a link to it in the path, then you would set
the E<lt>propertyE<gt> tags like this:

 <property name="title" value="My Home Page">
 <property name="path-title" value="Home">

title() would be called like this:

 $page->title(path=>1)

=head3 $page->parent()

parent() returns the page's parent page.  Be careful to avoid confusing the
terms "caller" and "parent".  "caller" is the page that is embedding the
page represented by this object.  "parent" is the page that is one step up in
the web site hierarchy.  The parent page is always going to be either a
directory index file or (for the home page) nothing.

=head3 $page->path_pages()

path_pages() returns an array of the pages in the web site hierarcy leading
down to and including the page represented by this object. In array context
this method returns an array.  In scalar context it returns an array reference.

=head3 $page->link_path()

This method returns the URL path to link to the page represented by this
object. This method always returns an absolute path.

=head2 Web::XDO::Token

This class represents a generic token in an XDO page.  All token classes
superclass this class.

=head3 $class->new()

Creates a new Web::XDO::Token object and returns it.  Doesn't do anything else.

=head3 $token->output()

Outputs $token->{'raw'} if it is defined. This method is overridden by many
tag classes.

=head2 Web::XDO::Token::Tag

This class represents a tag.  This is the default class for tags that XDO
doesn't recognize. This class superclasses
L<Web::XDO::Token|/Web::XDO::Token>.

=head3 $tag->add_class()

This method adds a CSS class to the tag's "class" attribute.  If such an
attribute doesn't already exist then it is created.  If the new CSS class
is already in the "class" attribute then no change is made.

After calling add_class() and before outputting the tag you should call
L<< $tag-E<gt>rebuild()|/$tag-E<gt>rebuild() >> or the output tag will not have the
added class.

=head3 $tag->rebuild()

rebuild() rebuilds the $tag->{'raw'} attribute.  'raw' is the string that is
output by L<< $token-E<gt>output()|/$token-E<gt>output() >>.

=head3 $tag->adjust_atts_for_root()

adjust_atts_for_root() modifies the given tag attributes if they have the
L<< E<lt>xdo-rootE<gt>|/Web::XDO::Token::Tag::XdoRoot >>
tag.

=head3 $tag->content()

Returns the elements contained within the tag represented by this object. The
elements are removed from the page's tokens array.  The end tag is removed from
the tokens array but is not returned by this method.

$tag->contents() is an alias for $tag->content().

=head3 $tag->included_page()

This method returns a page object representing the page referenced in a tag.
Most commonly this method is used by
L<< E<lt>includedE<gt>|/Web::XDO::Token::Tag::Include >>
to retrieve the included page.

=head3 $tag->output()

Outputs the tag.
L<< $tag-E<gt>adjust_atts_for_root()|/$tag-E<gt>adjust_atts_for_root() >>
is called before the tag is output.

=head2 Web::XDO::Token::Tag::Include

This class represents an E<lt>includeE<gt> tag.

=head3 $include->output()

$include->output() embeds the referenced page in the current page.

=head2 Web::XDO::Token::Tag::Property

This class represents a E<lt>propertyE<gt> tag.  That tag sets a page property.
It does not output anything.

=head3 $property->set_page_prop()

This method sets a property of the L<< top page|/$page-E<gt>top() >>.

=head3 $property->output()

This method sets a property of the L<< top page|/$page-E<gt>top() >> again. When an
XDO page is loaded the properties of the page are set as the page is parsed.
Because properties can be changed between parsing and output, the
E<lt>propertyE<gt> tag sets properties in both parsing and output.

=head2 Web::XDO::Token::Tag::ShowProperty

This class represents a E<lt>show-propertyE<gt> tag.

=head3 $show_property->output()

This method outputs the property of the L<< top page's|/$page-E<gt>top() >> that
is named in the "name" attribute. Note that the value of the property is not
HTML-escaped.

=head2 Web::XDO::Token::Tag::XdoRoot

This class represents an
L<< E<lt>xdo-rootE<gt>|http://idocs.com/xdo/guides/version-0-10/tags/xdo-root/ >>
tag.

=head3 $xdo_root->output()

This method outputs the
L<$xdo object's|/Web::XDO> {'root'} property.

=head2 Web::XDO::Token::Tag::Wrapper

This class represents a
L<< E<lt>wrapperE<gt>|http://idocs.com/xdo/guides/version-0-10/tags/wrapper/ >>
tag.

=head3 $wrapper->output()

This method includes the referenced page.  The contents of the
E<lt>wrapperE<gt> tag are used to the replace the included page's
L<< E<lt>wrapper-contentE<gt>|/Web::XDO::Token::Tag::WrapperContent >> tag.

=head2 Web::XDO::Token::Tag::WrapperContent

This class represents a
L<< E<lt>wrapper-contentE<gt>|http://idocs.com/xdo/guides/version-0-10/tags/wrapper/ >>
tag.

=head3 $wrapper_content->output()

This method does not do anything.  The E<lt>wrapper-contentE<gt> tag is a
placeholder. When a
L<< E<lt>wrapperE<gt>|/$wrapper-E<gt>output() >>
tag is output it removes the <E<lt>wrapper-contentE<gt> tag and substitutes in
its own contents.

=head2 Web::XDO::Token::Tag::XdoTest

This class represents an
L<< E<lt>xdo-testE<gt>|http://idocs.com/xdo/guides/version-0-10/tags/xdo-test/ >>
tag.

=head2 Web::XDO::Token::Tag::Parent

This class represents a
L<< E<lt>parentE<gt>|http://idocs.com/xdo/guides/version-0-10/tags/parent/ >>
tag.

=head2 Web::XDO::Token::Tag::Path

This class represents a
L<< E<lt>pathE<gt>|http://idocs.com/xdo/guides/version-0-10/tags/path/ >>
tag.

=head2 Web::XDO::Token::Tag::A

This class represents a
L<< E<lt>aE<gt>|http://idocs.com/xdo/guides/version-0-10/tags/a/ >>
tag.

=head1 TERMS AND CONDITIONS

Copyright (c) 2013 by Miko O'Sullivan.  All rights reserved.  This program is 
free software; you can redistribute it and/or modify it under the same terms 
as Perl itself. This software comes with B<NO WARRANTY> of any kind.

=head1 AUTHORS

Miko O'Sullivan
F<miko@idocs.com>

=head1 VERSION

=over 4

=item Version 0.10 - December 1, 2013

Initial release

=back

