package Markup;

use strict; use warnings;

use base 'Object';

use Markup::Text;
use Markup::Open;
use Markup::Close;
use Markup::Declaration;
use Markup::Comment;

use L;

# constructor
sub new {
	my ($class) = @_;
	my $self = $class->SUPER::new({elements => []});
	return $self;
}

# constructor
sub parse {
	my ($pkg, $html) = @_;
	my $self = $pkg->new();
	my @e;
	# this "parser" is inefficient, it moves the $html string around too much
	my $in_textarea = 0;
	while ($html ne "") {
		if ($html =~ s,^(\s*<.*?>\s*),,s) {
			# tag
			my $e = Markup::Tag->parse($1);
			if ($e->type eq "open" && $e->tag eq "textarea" && !$e->single) {
				$in_textarea = 1;
			} elsif ($e->type eq "close" && $e->tag eq "textarea") {
				$in_textarea = 0;
			}
			push @e, $e;
		} elsif ($html =~ m,^\s+\z,s) {
			last;
		} elsif ($html =~ s,^((?:<br>|[^<])+),,s) {
			# text
			# we regard "<br>" tags as part of the text so that text can include newlines
			# strip newlines off the end of the text (except one after a <br>);
			# they should be regarded as space attached to the following tag
			my $text = $1;
			if ($text =~ s,(<br>\n|)(\n+)\z,$1,s) {
				$html = "$2$html";
			}
			if ($in_textarea) {
				$text = textarea_html_to_text($text);
			} else {
				$text = html_to_text($text);
			}
			push @e, Markup::Text->new($text);
		} else {
			# brokenness
			die "cannot parse markup:\n".substr($html, 0, 500);
		}
	}
	$self->{elements} = \@e;
	return $self;
}

# constructor
sub parse_file {
	my ($pkg, $fh) = @_;
	my $self = $pkg->parse(slurp($fh));
	return $self;
}

sub html {
	my ($self) = @_;
	my $html = "";
	my $in_textarea = 0;
	for my $e (@{$self->{elements}}) {
		# special handling for textarea, how bogus!
		if ($e->type eq "open" && $e->tag eq "textarea" && !$e->single) {
			$in_textarea = 1;
		} elsif ($e->type eq "close" && $e->tag eq "textarea") {
			$in_textarea = 0;
		}
		if ($in_textarea && $e->type eq "text") {
			$html .= $e->textarea_html;
		} else {
			$html .= $e->html;
		}
	}
	return $html;
}

sub processor {
	my ($self) = @_;
	return Markup::Processor->new($self);
}

# for debug:
sub dump_elements {
	my ($self) = @_;
	print "------------------------------ start dump elements\n";
	for (@{$self->{elements}}) {
		print $_->type, "\t", $_->html, "\n";
	}
	print "------------------------------ end dump elements\n";
}

1
