/usr/local/CPAN/Text-Xatena/Text/Xatena/Node/List.pm
package Text::Xatena::Node::List;
use strict;
use warnings;
use base qw(Text::Xatena::Node);
use constant {
UL => qr/^-/,
OL => qr/^\+/,
};
sub parse {
my ($class, $s, $parent, $stack) = @_;
if ($s->scan(UL)) {
my $node = $class->new([ $s->matched->[0] ]);
until ($s->eos || !$s->scan(UL)) {
push @$node, $s->matched->[0];
}
push @$parent, $node;
return 1;
}
# same as above except regexp (unrolled for performance)
if ($s->scan(OL)) {
my $node = $class->new([ $s->matched->[0] ]);
until ($s->eos || !$s->scan(OL)) {
push @$node, $s->matched->[0];
}
push @$parent, $node;
return 1;
}
}
sub as_struct {
my ($self) = @_;
my $stack = [ { children => [] } ];
my $children = $self->children;
for my $line (@$children) {
my ($symbol, $text) = ($line =~ /^([-+]+)\s*(.+)$/);
my $level = length($symbol);
pop @$stack while (scalar @$stack > $level * 2);
while (scalar @$stack < $level * 2) {
my $node = +{
name => (substr($line, $level - 1, 1) eq '+' ? 'ol' : 'ul'),
children => []
};
push @{ $stack->[-1]->{children} }, $node if @$stack;
push @$stack, $node;
}
my $node = +{
name => 'li',
children => [ $text ]
};
push @{ $stack->[-1]->{children} }, $node;
push @$stack, $node;
}
$stack->[1];
}
sub as_html {
my ($self, %opts) = @_;
$self->_as_html($self->as_struct, %opts);
}
sub _as_html {
my ($self, $obj, %opts) = @_;
my $ret = "<" . $obj->{name} . ">";
$ret .= "\n" unless $obj->{name} eq 'li';
for my $child (@{ $obj->{children} }) {
if (ref($child)) {
$ret .= $self->_as_html($child, %opts);
} else {
$ret .= $self->inline($child, %opts);
}
}
$ret .= "</" . $obj->{name} . ">\n";
$ret;
}
1;
__END__