CPAN::Forum::Markup - Markup definitions and processing for CPAN::Forum


CPAN-Forum documentation Contained in the CPAN-Forum distribution.

Index


Code Index:

NAME

Top

CPAN::Forum::Markup - Markup definitions and processing for CPAN::Forum

SYNOPSIS

Top

	my $markup = CPAN::Forum::Markup->new();
	my $result = $markup->posting_process($new_text) ;

DESCRIPTION

Top

Based on Parse::RecDescent, this module provide a method to check if a give piece of text is a valid post. It returns the text in the format it could be sent to the user or returns undef if the text is invalid.


CPAN-Forum documentation Contained in the CPAN-Forum distribution.

package CPAN::Forum::Markup;
use strict;
use warnings;

use CGI qw();
use Parse::RecDescent;

sub new {
	my ($class) = @_;
	my $self = bless {}, $class;
	
	$self->{grammar} = q {
		entry      : chunk(s) eodata                  { $item[1] }
		chunk      : marked_html | marked_code        { $item[1] }

		marked_html: html(s)                          { qq(<div class="text">) . join("", @{$item[1]}) . qq(</div>); }
		html       : text                             { $item[1] } 
	           	           | block                            { $item[1] }
			   			   | inline                           { $item[1] }
		block      : open_p inline(s) close_p         { "<p>" . join("", @{$item[2]}) . "</p>" } 


		inline     : text                             { $item[1] }
	           	           | open_b text close_b              { join "", @item[1..$#item] }
	           	           | open_i text close_i              { join "", @item[1..$#item] }
			   			   | br                               { $item[1] }
			   			   | open_a text close_a              { join "", @item[1..$#item] }

		br         : m{<br( /)?>}i                    { "<br />" }
		open_p     : m{<p>}i                          { "<p>"  }
		close_p    : m{</p>}i                         { "</p>" }
		open_b     : m{<b>}i                          { "<b>"  }
		close_b    : m{</b>}i                         { "</b>" }
		open_i     : m{<i>}i                          { "<i>"  }
		close_i    : m{</i>}i                         { "</i>" }

		open_a      : open_a_href urlx open_a_gt      { qq(<a href="$item[2]">) }
		open_a_href : m{<a href=}i
		urlx        : quote url quote                 {$item[2]}
								| url                             {$item[1]}
		url         : http
	            	            | mailto
		http        : m{http://[^">]+}i               { lc $item[1]  }
		mailto      : m{mailto:[^">]+}i               { lc $item[1]  }   
		open_a_gt   : m{>}     
		quote       : m{"}

		close_a    : m{</a>}i                         { "</a>" }


		text       : m{[\r\t\n -;=?-~]+}              {$item[1] }

		marked_code: open_code code close_code        { join("", @item[1..$#item]) }
		open_code  : m{<code>}                        { qq(<div class="code">) }
		close_code : m{</code>}                       { qq(</div>) }
		code       : m{[\r\t\n -~]+?(?=</code>)}      { CPAN::Forum::Markup::split_rows(join "", @item[1..$#item]) }

		eodata     : m{^\Z}
		};

	$Parse::RecDescent::skip = '';

	return $self;
}



# takes a string
# makes sure every line is max N characters long
sub split_rows {
	my ($text, $N) = @_;
	$N ||= 100;
	my $NEXTMARK = '<span class="nextmark">+</span>';

	my @text = split /\n/, $text;
	my @new;
	while (@text) {
		my $row = shift @text;
		if (length $row <= $N) {
			push @new, CGI::escapeHTML($row);
			next;
		}
		push @new, CGI::escapeHTML(substr($row, 0, $N-1, ""));
		while (length $row > $N) {
			push @new,  $NEXTMARK . CGI::escapeHTML(substr($row, 0, $N-2, ""));
		}
		push @new, $NEXTMARK . CGI::escapeHTML($row);
		
	}
	return join "\n", @new;
}

sub parser {
	my ($self) = @_;
	return Parse::RecDescent->new($self->{grammar});
}

sub posting_process {
	my ($self, $text) = @_;

	my $parser = $self->parser;
	if (not $parser) {
		warn "Bad Grammar\n";
		return;
	}
	my $out = $parser->entry($text);
	return if not defined $out;
	return join("",@$out);
}



1;