package HTML::WikiConverter::WebApp;
use base 'CGI::Application';
use HTML::WikiConverter;
use XML::Writer;
use Tie::IxHash;
use Encode;
=head1 NAME
HTML::WikiConverter::WebApp - Web interface to HTML::WikiConverter
=head1 SYNOPSIS
Inside the index.cgi instance script (which is included with this
distribution):
#!/usr/bin/perl
use HTML::WikiConverter::WebApp;
my %config = (
template_path => '/path/to/web/templates',
);
HTML::WikiConverter::WebApp->new( PARAMS => \%config )->run;
=head1 DESCRIPTION
This module provides a L interface to
L and all installed dialect modules.
Refer to the INSTALL file for installation instructions.
=head1 QUERY PARAMETERS
This application accepts a number of query parameters to control its
behavior. The most basic is the run mode parameter, C. This
application can be in one of two run modes: C<"new"> or C<"convert">.
(These correspond to the C and C methods,
respectively.) C<"new"> causes a new page to be displayed, while
C<"convert"> displays the results of html-to-wiki conversion.
Additional query parameters can be passed independent of run mode:
=over 4
=item * source_type
One of C<"raw_html">, C<"from_uri">, or C<"sample_html">.
=item * dialect
Any installed dialect, eg C<"MediaWiki">.
=item * base_uri
Base URL to be used for converting relative links to absolute ones.
=item * wiki_uri
Template for wiki URLs. When scanning the HTML source, if a URL (as in
an C or C
attribute value) is found matching this
template, it will be treated to a link to a wiki
article/image. Consult L for more
information.
Note that this is a bit less flexible than using the C
attribute directly in L. That attribute allows
multiple templates, allows coderefs, and regexps, etc. This option
only accepts a single scalar representing a very simple wiki URL
template.
=item * show_parsed_html
If enabled, an additional textarea containing the parsed HTML will be
displayed.
=item * escape_entities
If enabled, unsafe HTML entities ("E", "E", and "E") will
be encoded using L.
=item * format
One of C<"html"> or C<"xml">. Determines the type of output displayed
by this application.
=back
=head1 METHODS
=head2 setup
Sets up the app for L.
=cut
sub setup {
my $self = shift;
$self->error_mode( 'display_error' );
$self->tmpl_path( $self->param('template_path') );
$self->mode_param( 'm' );
$self->start_mode( 'new' );
$self->run_modes(
new => 'new_page',
convert => 'output_page',
);
$self->header_add( -charset => 'utf-8' );
}
=head2 new_page
Corresponds to the C run mode. Returns a blank form. If arguments
are available on the CGI query string, these are used as default
values for the form fields.
=cut
sub new_page {
my $self = shift;
my $q = $self->query;
my $tmpl = $self->load_template( 'main.html' );
$tmpl->param(
$self->_default_template_params,
);
$tmpl->output;
}
=head2 output_page
Corresponds to the C run mode. Same as C but returns
the wiki markup for the provided html as well.
=cut
sub output_page {
my $self = shift;
my $q = $self->query;
my $source_type = $q->param('source_type') or die "need source_type";
my $dialect = $q->param('dialect') or die "need dialect";
die "unknown source_type '$source_type'" unless $self->_known_source_type( $q->param('source_type') );
my %source;
SWITCH: {
%source = ( html => $q->param('html') ), last if $source_type eq 'raw_html';
%source = ( html => $self->_sample_html ), last if $source_type eq 'sample_html';
%source = ( uri => $q->param('uri') ), last if $source_type eq 'from_uri';
};
die sprintf( "no %s was provided", (keys %source)[0] ) unless ( (values %source)[0] );
my $wc = new HTML::WikiConverter(
dialect => $dialect,
base_uri => $q->param('base_uri'),
wiki_uri => $q->param('wiki_uri'),
escape_entities => $q->param('escape_entities'),
);
my $wiki = $wc->html2wiki( %source );
my $parsed_html = $wc->parsed_html;
$source{html} = decode( $wc->encoding, $source{html} ) if $source{html};
$wiki = decode( $wc->encoding, $wiki ) if $wiki;
my $format = $q->param('format') || 'html';
if( $format eq 'xml' ) {
tie( my %default_template_params, 'Tie::IxHash' );
%default_template_params = $self->_default_template_params;
my %ignore_params = map { $_ => 1 } qw(
dialects
error
raw_html
from_uri
sample_html
uri
);
my $xml = '';
my $writer = new XML::Writer( OUTPUT => \$xml, DATA_MODE => 1, DATA_INDENT => 2 );
$writer->xmlDecl('utf-8');
$writer->startTag( 'wikitool', application => 'html2wiki' );
$writer->startTag( 'query' );
$writer->startTag( 'source', type => $source_type );
$writer->characters( (values %source)[0] );
$writer->endTag();
$writer->startTag( 'options' );
while( my( $f, $v ) = each %default_template_params ) {
next if $ignore_params{$f};
$writer->startTag( $f );
$writer->characters( $v );
$writer->endTag();
}
$writer->endTag();
$writer->endTag();
$writer->startTag( 'response' );
if( $q->param('show_parsed_html') ) {
$writer->startTag( 'parsed_html' );
$writer->characters( $parsed_html );
$writer->endTag();
}
$writer->startTag( 'wiki_markup' );
$writer->characters( $wiki );
$writer->endTag();
$writer->endTag();
$writer->endTag();
$self->header_add( -type => 'text/xml' );
return $xml;
}
my $temp = $self->load_template( 'main.html' );
$temp->param(
$self->_default_template_params,
uri => $source{uri},
html => $source{html},
parsed_html => $parsed_html,
wiki_markup => $wiki,
);
return $temp->output;
}
sub _default_template_params {
my $self = shift;
my $q = $self->query;
my $source_type = $self->_known_source_type( $q->param('source_type') ) ? $q->param('source_type') : 'raw_html';
return (
dialect => $q->param('dialect') || '',
$source_type => 1,
uri => $q->param('uri') || '',
base_uri => $q->param('base_uri') || '',
wiki_uri => $q->param('wiki_uri') || '',
show_parsed_html => $q->param('show_parsed_html') || 0,
escape_entities => $q->param('escape_entities') || 0,
dialects => $self->_dialects,
error => '',
);
}
my %known_source_types = map { $_ => 1 } qw(
from_uri
raw_html
sample_html
);
sub _known_source_type {
my( $self, $type ) = @_;
return exists $known_source_types{$type};
}
sub _dialects {
my $self = shift;
my $q = $self->query;
my $selected_dialect = $q->param('dialect') || '';
my @dialects;
my %seen;
foreach my $dialect ( HTML::WikiConverter->available_dialects ) {
next if $seen{$dialect}++;
push @dialects, { dialect => $dialect, selected => ( $selected_dialect eq $dialect ) };
}
return \@dialects;
}
=head2 load_template
Loads the specified L template.
=cut
sub load_template {
my( $self, $file ) = @_;
return $self->load_tmpl( $file, die_on_bad_params => 1, loop_context_vars => 1, cache => 1 );
}
sub _sample_html {
my $self = shift;
return $self->load_template( 'sample_html.html' )->output;
}
=head2 display_error
Error-catching method called by L if a run mode
fails for any reason. Displays a basic form with a styled error
message up top.
=cut
sub display_error {
my( $self, $error ) = @_;
if( $error =~ /Dialect .* could not be loaded/ ) {
$error = sprintf q{The "%s" dialect either doesn't exist or has not been installed.}, $self->query->param('dialect');
}
$error =~ s{(.*?) at \S+ line \d+\.}{$1.};
$error = ucfirst $error;
my $tmpl = $self->load_template( 'main.html' );
$tmpl->param(
$self->_default_template_params,
error => $error
);
return $tmpl->output;
}
=head1 AUTHOR
David J. Iberri, C<< >>
=head1 BUGS
Please report any bugs or feature requests to C, or through the web interface at
L.
I will be notified, and then you'll automatically be notified of
progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc HTML::WikiConverter::WebApp
You can also look for information at:
=over 4
=item * AnnoCPAN: Annotated CPAN documentation
L
=item * CPAN Ratings
L
=item * RT: CPAN's request tracker
L
=item * Search CPAN
L
=back
=head1 COPYRIGHT & LICENSE
Copyright (c) David J. Iberri, all rights reserved.
This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
1;