File Coverage

lib/Convert/Wiki/Node.pm
Criterion Covered Total %
statement 78 78 100.0
branch 22 22 100.0
condition 8 10 80.0
subroutine 16 16 100.0
pod 7 9 77.7
total 131 135 97.0


line stmt bran cond sub pod time code
1             #############################################################################
2             # (c) by Tels 2004. Part of Convert::Wiki
3             #
4             #############################################################################
5              
6             package Convert::Wiki::Node;
7              
8 8     8   23976 use 5.006001;
  8         34  
  8         349  
9 8     8   42 use strict;
  8         14  
  8         285  
10 8     8   40 use warnings;
  8         13  
  8         255  
11              
12 8     8   50 use vars qw/$VERSION/;
  8         13  
  8         9373  
13              
14             $VERSION = '0.04';
15              
16             #############################################################################
17              
18             sub new
19             {
20 65     65 0 5214 my $class = shift;
21              
22 65         92 my $args = $_[0];
23 65 100       214 $args = { @_ } if ref($args) ne 'HASH';
24            
25 65         185 my $self = bless {}, $class;
26              
27             # XXX TODO check arguments
28            
29 65 100       181 if (defined $args->{type})
30             {
31 54         119 my $type = ucfirst($args->{type});
32 54 100       125 $type = 'Para' if $type eq 'Paragraph';
33              
34 54 100       178 if ($type =~ /(\d)\z/)
35             {
36             # convert XX9 => XX (for Head1 etc)
37 15   50     73 $args->{level} = abs($1 || 1);
38 15         56 $type =~ s/\d\z//;
39             }
40              
41 54 100 50     203 $self->error('Node type must be one of Head, Item, Mono, Line or Para but is \'' . $type . "'") and return $self
42             unless $type =~ /^(Head|Item|Line|Mono|Para)\z/;
43              
44 53         86 $class .= '::' . $type;
45 53         193 $self = bless $self, $class; # rebless
46             }
47              
48 64 100       169 if ($class ne __PACKAGE__)
49             {
50 63         100 my $pm = $class; $pm =~ s/::/\//g; # :: => /
  63         251  
51 63         104 $pm .= '.pm';
52 63         11889 require $pm; # XXX not very portable I am afraid
53             }
54              
55 64         256 $self->_init($args);
56             }
57              
58             sub _init
59             {
60             # generic init, override in subclasses
61 64     64   102 my ($self,$args) = @_;
62              
63 64         217 foreach my $k (keys %$args)
64             {
65 167         443 $self->{$k} = $args->{$k};
66             }
67            
68 64         174 $self->{error} = '';
69 64 100       195 $self->{txt} = '' unless defined $self->{txt};
70              
71 64         185 $self->{txt} =~ s/\n+\z//; # remove trailing newline
72 64         97 $self->{txt} =~ s/^\n+//; # remove newlines at start
73            
74 64         113 $self->{prev} = undef;
75 64         103 $self->{next} = undef;
76              
77 64         219 $self;
78             }
79              
80             sub _as_wiki
81             {
82 3     3   6 my ($self,$txt) = @_;
83              
84 3         629 $txt;
85             }
86              
87             sub as_wiki
88             {
89 55     55 1 207 my ($self, $wiki) = @_;
90              
91 55         180 $self->_as_wiki( $self->interlink($wiki) );
92             }
93              
94             sub interlink
95             {
96             # turn text in pragraph into links
97 48     48 0 70 my ($self, $wiki) = @_;
98              
99 48         80 my $txt = $self->{txt};
100             # for all phrases, find them case-insensitive, then link them
101 48         64 for my $link (@{$wiki->{interlink}})
  48         126  
102             {
103             # turn "Foo" into "Foo|Foo"
104 64 100       210 $link .= '|' . $link unless $link =~ /\|/;
105             # split "Foobar|Foo" into "Foobar", "Foo"
106 64         183 my ($target, $phrase) = split /\|/, $link;
107              
108 64         124 my $p = quotemeta(lc($phrase));
109              
110 64 100       155 if ($target =~ /^[a-z]+:/)
111             {
112 8         103 $txt =~ s/([^a-z])($p)([^a-z]|$)/${1}[$target ${2}]$3/i;
113              
114             }
115             else
116             {
117             # no /g, since we want to interlink the phrase only once per paragraph
118             # XXX TODO: this will turn "foo" into [[foo[[bar]]]] when searching
119             # for bar after "foobar|foo"
120 56 100 100     18760 $txt =~ s/([^a-z]|^)($p)([^a-z]|$)/ "${1}[[$target" . ( ($2 eq $phrase && $2 eq $target) ? '' : "|$2") . "]]$3"/ie;
  7         223  
121             }
122             }
123 48         224 $txt;
124             }
125              
126             sub error
127             {
128 10     10 1 3161 my $self = shift;
129              
130 10 100       41 $self->{error} = $_[0] if defined $_[0];
131 10         72 $self->{error};
132             }
133              
134             sub type
135             {
136 18     18 1 30 my $self = shift;
137              
138             # XXX head1 => head
139 18         41 my $type = ref($self); $type =~ s/.*:://; # only last part
  18         125  
140 18         105 lc($type); # head, para, node etc
141             }
142              
143             sub prev_by_type
144             {
145             # find a previous node with a certain type
146 22     22 1 745 my ($self,$type) = @_;
147              
148 22         38 my $prev = $self->{prev};
149              
150             # print "Looking for '$type'\n";
151             # print "# At $prev $prev->{type}\n" if defined $prev;
152              
153 22   100     201 while (defined $prev && $prev->{type} !~ /$type/)
154             {
155 12         64 $prev = $prev->{prev};
156             # print "# At $prev $prev->{type}\n" if defined $prev;
157             }
158             # found something, or hit the first node (aka undef)
159 22         86 $prev;
160             }
161              
162             sub prev
163             {
164 21     21 1 41 my $self = shift;
165              
166 21         124 $self->{prev}
167             }
168              
169             sub next
170             {
171 6     6 1 13 my $self = shift;
172              
173 6         23 $self->{next};
174             }
175              
176             sub link
177             {
178 40     40 1 63 my $self = shift;
179              
180 40         59 $self->{next} = $_[0];
181 40         65 $self->{next}->{prev} = $self;
182              
183 40         73 $self;
184             }
185              
186             sub _remove_me
187             {
188 43     43   103 0;
189             }
190              
191             1;
192             __END__