# ---------------------------------------------------------------------------------------------------------------------- # GX Framework (c) 2009-2011 Jörg A. Uzarek # File: GX/Exception/Formatter/HTML.pm # ---------------------------------------------------------------------------------------------------------------------- package GX::Exception::Formatter::HTML; use GX::HTML::Util qw( escape_html ); use Scalar::Util qw( blessed ); # ---------------------------------------------------------------------------------------------------------------------- # Class setup # ---------------------------------------------------------------------------------------------------------------------- use GX::Class::Object; build; # ---------------------------------------------------------------------------------------------------------------------- # Public methods # ---------------------------------------------------------------------------------------------------------------------- sub format { my $self = ref $_[0] ? shift : shift->new; my $exception = shift; return unless blessed $exception && $exception->isa( 'GX::Exception' ); my @html; push @html, '
'; push @html, '

' . ref( $exception ) . '

'; push @html, '
', '' . join( '
', split( /\n/, escape_html( $exception->as_string( 0 ) ) ) ) . '
', '
'; my @subexceptions; for ( my $subexception = $exception->subexception; $subexception; $subexception = $subexception->subexception ) { push @subexceptions, $subexception; } if ( @subexceptions ) { push @html, '
', '

Subexceptions

'; for my $subexception ( @subexceptions ) { push @html, '
', '' . join( '
', split( /\n/, escape_html( $subexception->as_string( 0 ) ) ) ) . '
', '
'; } push @html, '
'; } if ( $exception->stack_trace ) { push @html, '
', '

Stack trace

', '
    '; for my $frame ( $exception->stack_trace ) { my $subroutine = $frame->subroutine or next; my $filename = $frame->filename or next; my $line = $frame->line or next; push @html, '
  1. '; if ( $subroutine eq '(eval)' ) { push @html, sprintf( "

    (eval) in %s at line %s

    ", escape_html( $filename ), escape_html( $line ) ); } else { push @html, sprintf( "

    %s called in %s at line %s

    ", escape_html( $subroutine ), escape_html( $filename ), escape_html( $line ) ); } # We don't know the encoding of the source file, so we'll have to guess ... if ( -f $filename && open( my $fh, '<:encoding(utf8)', $filename ) ) { my $first_line = $line - 5; my $last_line = $line + 5; $first_line = 1 if $first_line < 1; push @html, '
    ', '', ''; my $current_line = 0; while ( <$fh> ) { $current_line++; next if $current_line < $first_line; last if $current_line > $last_line; my $source = $_; chomp( $source ); $source = escape_html( $source ); $source =~ s/\s/ /g; push @html, '', '', '', ''; } close $fh; push @html, '', '
    ' . $current_line . '' . $source . '
    ', '
    '; } push @html, '
  2. '; } push @html, '
', '
'; } push @html, '
'; return join( "\n", @html ) . "\n"; } 1; __END__ =head1 NAME GX::Exception::Formatter::HTML - Helper class for rendering exceptions as HTML =head1 SYNOPSIS None. =head1 DESCRIPTION This module provides the L class which extends the L class. =head1 METHODS =head2 Constructor =head3 new Returns a new L object. $formatter = GX::Exception::Formatter::HTML->new; =over 4 =item Returns: =over 4 =item * C<$formatter> ( L object ) =back =back =head2 Public Methods =head3 format Renders the given exception object as HTML. $html = $formatter->format( $exception ); =over 4 =item Arguments: =over 4 =item * C<$exception> ( L object ) =back =item Returns: =over 4 =item * C<$html> ( string ) =back =back This method can also be called as a class method. =head1 SEE ALSO =over 4 =item * L =back =head1 AUTHOR JErg A. Uzarek Euzarek@runlevelnull.deE =head1 COPYRIGHT AND LICENSE Copyright (c) 2009-2011 JErg A. Uzarek. This module is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License Version 3 as published by the Free Software Foundation. =cut