Web-XDO

 view release on metacpan or  search on metacpan

lib/Web/XDO.pm  view on Meta::CPAN

=cut


#------------------------------------------------------------------------------
# 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

=cut

sub new {
	my ($class, $url_root, $url_rel_path, $xdo, %opts) = @_;
	my ($tokens, $token_idx, $page);
	
	# TESTING
	# println $class, '->new()'; ##i
	
	# create page object
	$page = $class->SUPER::new();
	
	# don't recognize cdata tags
	$page->xml_mode(1);
	
	# must either designate a caller or explicitly set as top page
	if (my $caller = $opts{'caller'}) {
		if (UNIVERSAL::isa($caller, 'Web::XDO::Page')) {
			$page->{'caller'} = $caller;
		}
		else {
			croak q|caller is not a page object|;
		}
	}
	else {
		$page->{'props'} = {};
	}
	
	# hold on to xdo object
	$page->{'xdo'} = $xdo;
	
	# build path to file
	$page->set_paths($url_root, $url_rel_path) or return 0;
	
	# initialize token array
	$tokens = $page->{'tokens'} = [];
	
	# parse
	$page->parse_file("$page->{'local_path'}");
	
	# initialize $token_idx to 0
	$token_idx = 0;
	
	# set page properties
	# NOTE: This rather odd construction for iterating through the tokens is
	# based on the fact that set_page_prop tokens are removed from the token
	# array, and they might remove other tokens after them.  Therefore the
	# length of the array can change during the loop.
	while ($token_idx < @$tokens) {
		my $token = $tokens->[$token_idx];
		
		if (UNIVERSAL::isa($token, 'Web::XDO::Token::Tag')) {
			if (UNIVERSAL::can($token, 'set_page_prop')) {
				$token->set_page_prop($page, $token_idx);
			}
		}
		
		# increment to next token
		$token_idx++;
	}
	
	# return
	return $page;
}
#
# new
#------------------------------------------------------------------------------


#------------------------------------------------------------------------------
# top
#

lib/Web/XDO.pm  view on Meta::CPAN

	$tokens = $page->{'tokens'};
	
	# check if this page has already been output
	if ($nested->{$local_path}) {
		return 0;
	}
	
	# note as output
	$nested->{$local_path} = 1;
	
	# loop through tokens
	while ($token_idx <= $#$tokens) {
		my $token = $tokens->[$token_idx];
		
		# if object, call output method
		# else just print
		if (ref $token) {
			$token->output($page, $token_idx);
		}
		else {
			print $token;
		}
		
		# increment
		$token_idx++;
	}
	
	# note not longer output
	delete $nested->{$local_path};
}
#
# output
#------------------------------------------------------------------------------


#------------------------------------------------------------------------------
# start
#

=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()>.

=cut

sub start {
	my ($page, $tag_name, $atts, $att_order, $raw) = @_;
	my ($self_ender, $def, $token, $xdo);
	$xdo = $page->{'xdo'};
	
	# TESTING
	# println $tag_name, '->start'; ##i
	
	# normalize tag name
	# NOTE: We need to normalize here because the parser is in xml_mode. That
	# mode is on so that content of cdata tags (specificall <title>) are
	# parsed. It has the side-effect that tag names are sent as they appear
	# in the document being parsed.  If anybody knows a more global way to send
	# lowercased tag names I'll be glad to hear about it.  - Miko
	$tag_name = lc($tag_name);
	
	# if the tag has a trailing slash then it's a self-ender
	if ($raw =~ m|/\s*\>$|s)
		{ $self_ender = 1 }
	
	# NOTE: Funky code ahead. The following few lines take into account several
	# different possibilities of how the tag definition might be structured.
	# It might be:
	#    - a hashref with a class name
	#    - a hashref without a class name
	#    - just a class name
	#
	# The following code ensures that the definition is a hashref with a
	# class name.
	
	# get tag definition
	$def = $page->{'xdo'}->{'tags'}->{$tag_name} || $xdo->default_tag_class();
	
	# ensure tag definition is a hashref
	ref($def) or $def = {class=>$def};
	
	# ensure definition has a tag class
	$def->{'class'} ||= $xdo->default_tag_class();
	
	# create token object
	$token = $def->{'class'}->new();
	$token->{'type'} = 'tag';
	$token->{'name'} = $tag_name;
	$token->{'atts'} = $atts;
	$token->{'raw'} = $raw;
	
	# note if self-ender
	if ($self_ender)
		{ $token->{'self_ender'} = 1 }
	
	# hold on to token
	push @{$page->{'tokens'}}, $token;
}
#
# start
#------------------------------------------------------------------------------



#------------------------------------------------------------------------------
# end
#

=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.

=cut

sub end {
	my ($page, $tag_name, $raw) = @_;
	my ($token);
	
	# normalize tag name
	# NOTE: We need to normalize here because the parser is in xml_mode. That
	# mode is on so that content of cdata tags (specificall <title>) are
	# parsed. It has the side-effect that tag names are sent as they appear
	# in the document being parsed.  If anybody knows a more global way to send
	# lowercased tag names I'll be glad to hear about it.  - Miko
	$tag_name = lc($tag_name);
	
	# create token object
	$token = Web::XDO::Token::EndTag->new();
	$token->{'type'} = 'end_tag';
	$token->{'name'} = $tag_name;
	$token->{'raw'} = $raw;
	
	# hold on to token
	push @{$page->{'tokens'}}, $token;
}
#
# end
#------------------------------------------------------------------------------



#------------------------------------------------------------------------------
# text
#

=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.

=cut

sub text {
	my ($page, $raw) = @_;
	my ($token);
	
	# create text object
	$token = Web::XDO::Token::Text->new();
	$token->{'type'} = 'text';
	$token->{'raw'} = $raw;
	
	# hold on to token
	push @{$page->{'tokens'}}, $token;
}
#
# text
#------------------------------------------------------------------------------


#------------------------------------------------------------------------------
# is_directory_index
#

=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.



( run in 2.838 seconds using v1.01-cache-2.11-cpan-524268b4103 )