package Text::Styler::Parser; use strict; use HTML::Parser; our @ISA = qw( HTML::Parser ); use vars qw( $VERSION ); $VERSION = 0.1; my %inline_tags = ( 'a' => '[', 'b' => '*', 'strong' => '*', 'i' => '\\', 'em' => '\\', 'q' => '"' ); my %block_tags = ( 'p' => "\n", 'pre' => '' ); my %empty_tags = ( 'br' => '1' ); my @report_tags = (keys %inline_tags, keys %block_tags, keys %empty_tags); my $tag_symbols = { %inline_tags, %block_tags }; # not too concerned about saving memory right now my $tag_handlers= { 'a' => \&hdlr_hyperlink, 'p' => \&hdlr_paragraph, 'br' => \&hdlr_br, 'pre' => \&hdlr_pre }; sub new { my $proto = shift; my $class = ref( $proto ) || $proto; my $parser = HTML::Parser->new( api_version => 3 ); $parser->handler(start_document => \&start_document_handler, 'self' ); $parser->handler(start => \&start_handler, 'self, tagname, attr' ); $parser->handler(end => \&end_handler, 'self, tagname' ); $parser->handler(text => \&text_handler, 'self, dtext' ); #$parser->report_tags( qw( a b strong i em q p pre br ) ); #$parser->report_tags( qw( @report_tags ) ); $parser->unbroken_text(1); return bless $parser, $class; } sub contents { $_[0]->{_output}; } sub start_document_handler { $_[0]->{_stack}=undef; $_[0]->{_output}=undef; } sub start_handler { my $self = shift; my $tag = shift; my $attr = shift; push( @{ $self->{_stack} }, [ $tag, $tag_symbols->{$tag} ] ); unless( defined( $tag_handlers->{$tag} ) && $tag_handlers->{$tag}->($self,'1',$tag_symbols->{$tag},$attr)) { $self->{_output} .= length( $tag_symbols->{$tag} ) ? ' '.$tag_symbols->{$tag} : $tag_symbols->{$tag}; # default start handler } } sub end_handler { my $self = shift; my $tag = shift; unless( defined( $tag_handlers->{$tag} ) && $tag_handlers->{$tag}->($self,'-1',$tag_symbols->{$tag}) ) { if ( defined( $block_tags{$tag} ) ) { $self->{_output} .= "\n\n"; } elsif ( defined( $inline_tags{$tag} ) ) { $self->{_output} .= length( $tag_symbols->{$tag} ) ? $tag_symbols->{$tag}.' ' : $tag_symbols->{$tag}; # default end handler } # empty tags can only have start tag routines } pop( @{ $self->{_stack} } ); } sub text_handler { my $self = shift; my $text = shift; if ( $self->{_stack}->[0] ) { # filters out text outside a tag. $self->{_current_text}=$text; # a kludge. my $tag = $self->current_element; unless( defined($tag) && defined( $tag_handlers->{$tag} ) && defined( $tag_symbols->{$tag}) && $tag_handlers->{$tag}->($self,'0',$tag_symbols->{$tag}) ) { $self->{_current_text}=~s/\r//sg; $self->{_current_text}=~s/^[\s\t]*//gm; $self->{_current_text}=~s/[\s\t]*$//gm; $self->{_current_text}=~s/\n/ /gs; } $self->{_output} .= $self->{_current_text}; $self->{_current_text} = undef; } } #--- tag handlers sub hdlr_hyperlink { my ($self, $mode, $symbol, $attr) = @_; if ($mode == 1) { $self->{_output}.=' '; $self->{_current_link} .= $attr->{'href'}; # add alt storage here. return 1; } elsif ($mode == -1) { $self->{_output} .= ' ['.$self->{_current_link}.'] '; $self->{_current_link}=undef; # blank alt storage here. return 1; } return 0; } sub hdlr_paragraph { my ($self, $mode, $symbol, $attr) = @_; if ( $mode == 1) { # pass through. return 1; } return 0; } sub hdlr_br { my ($self, $mode, $symbol, $attr) = @_; if ($mode == 1) { $self->{_output}.="\n"; } return 1; # This handles it or we ignore it. } sub hdlr_pre { my ($self, $mode, $tag, $attr) = @_; if ( $mode==0 ) { # pass through. return 1; } return 0; } sub current_element { return shift->{_stack}->[-1]->[0] } #if defined. 1;