Convert::Wiki::Node - Represents a node (headline, paragraph etc) in a text


Convert-Wiki documentation Contained in the Convert-Wiki distribution.

Index


Code Index:

NAME

Top

Convert::Wiki::Node - Represents a node (headline, paragraph etc) in a text

SYNOPSIS

Top

	use Convert::Wiki::Node;

	my $head = Convert::Wiki::Node->new( txt => 'About Foo', type => 'head1' );
	my $text = Convert::Wiki::Node->new( txt => 'Foo is a foobar.', type => 'paragraph' );

	print $head->as_wiki(), $text->as_wiki();

DESCRIPTION

Top

A Convert::Wiki::Node represents a node (headline, paragraph etc) in a text. All the nodes together represent the entire document.

METHODS

Top

error()

	$last_error = $cvt->error();

	$cvt->error($error);			# set new messags
	$cvt->error('');			# clear error

Returns the last error message, or '' for no error.

as_wiki()

	my $txt = $node->as_wiki($wiki);

Return the contents of the node as wiki code. The parameter $wiki is the Convert::Wiki object the node belongs to. It can be used to access parameters like interlink.

type()

	my $type = $node->type();

Returns the type of the node as string.

prev()

	my $prev = $node->prev();

Get the node's previous node.

prev_by_type

	my $prev = $node->prev_by_type( $type );

Find a previous node with a certain type, for instance 'head' or 'line'.

next()

	my $next = $node->next();

Get the node's next node.

_remove_me()

	$rc = $node->_remove_me();

Internally called by Convert::Wiki to fix up the nodes after the first pass. A true return value indicates that this node must be removed entirely.

EXPORT

Top

None by default.

SEE ALSO

Top

Convert::Wiki.

AUTHOR

Top

Tels http://bloodgate.com

COPYRIGHT AND LICENSE

Top


Convert-Wiki documentation Contained in the Convert-Wiki distribution.

#############################################################################
# (c) by Tels 2004. Part of Convert::Wiki
#
#############################################################################

package Convert::Wiki::Node;

use 5.006001;
use strict;
use warnings;

use vars qw/$VERSION/;

$VERSION = '0.04';

#############################################################################

sub new
  {
  my $class = shift;

  my $args = $_[0];
  $args = { @_ } if ref($args) ne 'HASH';
  
  my $self = bless {}, $class;

  # XXX TODO check arguments
 
  if (defined $args->{type})
    { 
    my $type = ucfirst($args->{type});
    $type = 'Para' if $type eq 'Paragraph';

    if ($type =~ /(\d)\z/)
      {
      # convert XX9 => XX (for Head1 etc)
      $args->{level} = abs($1 || 1);
      $type =~ s/\d\z//;
      }

    $self->error('Node type must be one of Head, Item, Mono, Line or Para but is \'' . $type . "'") and return $self
      unless $type =~ /^(Head|Item|Line|Mono|Para)\z/;

    $class .= '::' . $type;
    $self = bless $self, $class;	# rebless
    }

  if ($class ne __PACKAGE__)
    {
    my $pm = $class; $pm =~ s/::/\//g;	# :: => /
    $pm .= '.pm';
    require $pm;			# XXX not very portable I am afraid
    }

  $self->_init($args);
  }

sub _init
  {
  # generic init, override in subclasses
  my ($self,$args) = @_;

  foreach my $k (keys %$args)
    {
    $self->{$k} = $args->{$k};
    }
  
  $self->{error} = '';
  $self->{txt} = '' unless defined $self->{txt};

  $self->{txt} =~ s/\n+\z//;		# remove trailing newline
  $self->{txt} =~ s/^\n+//;		# remove newlines at start
  
  $self->{prev} = undef;
  $self->{next} = undef;

  $self;
  }

sub _as_wiki
  {
  my ($self,$txt) = @_;

  $txt;
  }

sub as_wiki
  {
  my ($self, $wiki) = @_;

  $self->_as_wiki( $self->interlink($wiki) );
  }

sub interlink
  {
  # turn text in pragraph into links
  my ($self, $wiki) = @_;

  my $txt = $self->{txt};
  # for all phrases, find them case-insensitive, then link them
  for my $link (@{$wiki->{interlink}})
    {
    # turn "Foo" into "Foo|Foo"
    $link .= '|' . $link unless $link =~ /\|/;
    # split "Foobar|Foo" into "Foobar", "Foo"
    my ($target, $phrase) = split /\|/, $link;

    my $p = quotemeta(lc($phrase));

    if ($target =~ /^[a-z]+:/)
      {
      $txt =~ s/([^a-z])($p)([^a-z]|$)/${1}[$target ${2}]$3/i;

      }
    else
      {
      # no /g, since we want to interlink the phrase only once per paragraph
      # XXX TODO: this will turn "foo" into [[foo[[bar]]]] when searching
      # for bar after "foobar|foo"
      $txt =~ s/([^a-z]|^)($p)([^a-z]|$)/ "${1}[[$target" . ( ($2 eq $phrase && $2 eq $target) ? '' : "|$2") . "]]$3"/ie;
      }
    }
  $txt;
  }

sub error
  {
  my $self = shift;

  $self->{error} = $_[0] if defined $_[0];
  $self->{error};
  }

sub type
  {
  my $self = shift;

  # XXX head1 => head
  my $type = ref($self); $type =~ s/.*:://;		# only last part
  lc($type);						# head, para, node etc
  }

sub prev_by_type
  {
  # find a previous node with a certain type
  my ($self,$type) = @_;

  my $prev = $self->{prev};

#  print "Looking for '$type'\n";
#  print "# At $prev $prev->{type}\n" if defined $prev;

  while (defined $prev && $prev->{type} !~ /$type/)
    {
    $prev = $prev->{prev};
#    print "# At $prev $prev->{type}\n" if defined $prev;
    }
  # found something, or hit the first node (aka undef)
  $prev;
  }

sub prev
  {
  my $self = shift;

  $self->{prev}
  }

sub next
  {
  my $self = shift;

  $self->{next};
  }

sub link
  {
  my $self = shift;

  $self->{next} = $_[0];
  $self->{next}->{prev} = $self;

  $self;
  }

sub _remove_me
  {
  0;
  }

1;
__END__