File Coverage

blib/lib/Text/WikiFormat/SAX.pm
Criterion Covered Total %
statement 100 160 62.5
branch 16 36 44.4
condition 1 3 33.3
subroutine 20 30 66.6
pod n/a
total 137 229 59.8


line stmt bran cond sub pod time code
1             # $Id: SAX.pm,v 1.5 2003/01/04 00:27:25 matt Exp $
2              
3             package Text::WikiFormat::SAX;
4              
5             $VERSION = '0.03';
6 4     4   32876 use XML::SAX::Base;
  4         99646  
  4         168  
7             @ISA = qw(XML::SAX::Base);
8              
9 4     4   50 use strict;
  4         9  
  4         153  
10 4     4   3625 use XML::SAX::DocumentLocator;
  4         2136  
  4         1466  
11              
12             sub _parse_bytestream {
13 1     1   903 my ($self, $fh) = @_;
14 1         10 my $parser = Wiki::SAX::Parser->new();
15 1         4 $parser->set_parent($self);
16 1         4 local $/;
17 1         23 my $text = <$fh>;
18 1         5 $parser->parse($text);
19             }
20              
21             sub _parse_characterstream {
22 0     0   0 my ($self, $fh) = @_;
23 0         0 die "parse_characterstream not supported";
24             }
25              
26             sub _parse_string {
27 1     1   388 my ($self, $str) = @_;
28 1         7 my $parser = Wiki::SAX::Parser->new();
29 1         3 $parser->set_parent($self);
30 1         4 $parser->parse($str);
31             }
32              
33             sub _parse_systemid {
34 1     1   680 my ($self, $sysid) = @_;
35 1         8 my $parser = Wiki::SAX::Parser->new();
36 1         4 $parser->set_parent($self);
37 1 50       40 open(FILE, $sysid) || die "Can't open $sysid: $!";
38 1         3 local $/;
39 1         28 my $text = ;
40 1         5 $parser->parse($text);
41             }
42              
43             package Wiki::SAX::Parser;
44              
45 4     4   23 use strict;
  4         8  
  4         1974  
46              
47             sub new {
48 3     3   6 my $class = shift;
49 3         8 my $self = bless {}, $class;
50 3         10 return $self;
51             }
52              
53             sub set_parent {
54 3     3   5 my $self = shift;
55 3         19 $self->{parent} = shift;
56             }
57              
58             sub parent {
59 78     78   101 my $self = shift;
60 78         455 return $self->{parent};
61             }
62              
63             sub parse {
64 3     3   5 my $self = shift;
65            
66 3         10 my $sysid = $self->parent->{ParserOptions}->{Source}{SystemId};
67             $self->parent->set_document_locator(
68             XML::SAX::DocumentLocator->new(
69 0     0   0 sub { "" },
70 0     0   0 sub { $sysid },
71 0     0   0 sub { $self->{line_number} },
72 0     0   0 sub { 0 },
73 3         10 ),
74             );
75 3         342 $self->parent->start_document({});
76 3         1276 $self->parent->start_element(_element('wiki'));
77 3         327 $self->parent->characters({Data => "\n"});
78 3         95 $self->parent->comment({Data => " Text::WikiFormat::SAX v$Text::WikiFormat::SAX::VERSION "});
79 3         704 $self->parent->characters({Data => "\n"});
80            
81 3         42 $self->parse_wiki(shift);
82            
83 3         57 $self->parent->end_element(_element('wiki', 1));
84 3         254 $self->parent->end_document({});
85             }
86              
87             sub start_list {
88 0     0   0 my $self = shift;
89 0         0 my $type = shift;
90 0         0 $self->parent->start_element(_element("${type}list"));
91 0         0 $self->parent->characters({Data => "\n"});
92 0         0 $self->{in_list} = $type;
93             }
94              
95             sub end_list {
96 0     0   0 my $self = shift;
97 0         0 $self->parent->end_element(_element("$self->{in_list}list"));
98 0         0 $self->parent->characters({Data => "\n"});
99 0         0 $self->{in_list} = '';
100             }
101              
102 4     4   22 use vars qw($indent);
  4         6  
  4         6394  
103             $indent = qr/^(?:\t+|\s{4,})/;
104              
105             sub parse_wiki {
106 3     3   8 my $self = shift;
107 3         6 my ($text) = @_;
108 3         14 foreach my $line (split(/\n/, $text)) {
109 10 50       267 if ($line =~ /$indent(.*)$/) {
110 0         0 my $match = $1;
111 0 0       0 if ($match =~ /([\dA-Za-z]+)\.\s*(.*)$/) {
    0          
112             # ordered list
113 0         0 my $value = $1;
114 0         0 my $data = $2;
115 0 0       0 if ($self->{in_list} ne 'ordered') {
116 0 0       0 if ($self->{in_list}) {
117 0         0 $self->end_list();
118             }
119 0         0 $self->start_list('ordered');
120             }
121 0         0 my $el = _element('listitem');
122 0         0 _add_attrib($el, value => $value);
123 0         0 $self->parent->start_element($el);
124 0         0 $self->format_line($data);
125 0         0 $self->parent->end_element(_element('listitem', 1));
126 0         0 $self->parent->characters({Data => "\n"});
127             }
128             elsif ($match =~ /\*\s*(.*)$/) {
129             # bulleted list
130 0         0 my $data = $1;
131 0 0       0 if ($self->{in_list} ne 'itemized') {
132 0 0       0 if ($self->{in_list}) {
133 0         0 $self->end_list();
134             }
135 0         0 $self->start_list('itemized');
136             }
137 0         0 $self->parent->start_element(_element('listitem'));
138 0         0 $self->format_line($data);
139 0         0 $self->parent->end_element(_element('listitem', 1));
140 0         0 $self->parent->characters({Data => "\n"});
141             }
142             else {
143             # code
144 0 0       0 if ($self->{in_list}) {
145 0         0 $self->end_list();
146             }
147            
148 0         0 $self->parent->start_element(_element('code'));
149 0         0 $self->format_line($match);
150 0         0 $self->parent->end_element(_element('code', 1));
151 0         0 $self->parent->characters({Data => "\n"});
152             }
153             }
154             else {
155 10 50       37 if ($self->{in_list}) {
156 0         0 $self->end_list();
157             }
158 10         24 $self->format_line($line);
159             }
160             }
161             }
162              
163             sub format_line {
164 10     10   16 my $self = shift;
165 10         14 my ($text) = @_;
166            
167             my $strong = sub {
168 0     0   0 $self->parent->start_element(_element('strong'));
169 0         0 $self->parent->characters({Data => $_[0]});
170 0         0 $self->parent->end_element(_element('strong',1));
171 0         0 return '';
172 10         53 };
173             my $emphasized = sub {
174 0     0   0 $self->parent->start_element(_element('em'));
175 0         0 $self->parent->characters({Data => $_[0]});
176 0         0 $self->parent->end_element(_element('em',1));
177 0         0 return '';
178 10         57 };
179             my $line = sub {
180 0     0   0 $self->parent->start_element(_element('hr'));
181 0         0 $self->parent->end_element(_element('hr',1));
182 0         0 $self->parent->characters({Data => "\n"});
183 0         0 return '';
184 10         32 };
185             my $link = sub {
186 3     3   9 $self->make_link($_[0]);
187 3         299 return '';
188 10         31 };
189             my $data = sub {
190 12     12   27 $self->parent->characters({Data => $_[0]});
191 12         131 return '';
192 10         27 };
193            
194 10         29 $self->_format_line($text, $strong, $emphasized, $line, $link, $data);
195 10         21 $self->parent->start_element(_element('br'));
196 10         881 $self->parent->end_element(_element('br',1));
197 10         653 $self->parent->characters({Data => "\n"});
198             }
199              
200             sub _format_line {
201 13     13   42 my ($self, $text, $strong, $emphasized, $line, $link, $data) = @_;
202            
203 13 50       58 if ($text =~ s/^-{4,}//) {
204 0         0 $line->();
205             }
206            
207 13 100       109 if ($text =~ s/^(.*?)('')/$2/) {
    100          
    100          
208 1         7 $self->_format_line($1, $strong, $emphasized, $line, $link, $data);
209 1 50       19 if ($text =~ s/^'''(.*?)'''//) {
    50          
210 0         0 $strong->($1);
211             }
212             elsif ($text =~ s/^''(.*?)''//) {
213 0         0 $emphasized->($1);
214             }
215             else {
216 1         4 $text =~ s/^(.*)$//;
217 1         2 $data->($1);
218             }
219             }
220             elsif ($text =~ s/^(.*?)\[([^\]]+)\]//) {
221 1         5 $self->_format_line($1, $strong, $emphasized, $line, $link, $data);
222 1         10 $link->($2);
223             }
224             elsif ($text =~ s|^(.*?)(?=])\b([A-Za-z]+(?:[A-Z]\w+)+)||) {
225 2         6 $data->($1);
226 2         10 $link->($2);
227             }
228             else {
229 9         208 $text =~ s/^(.*)$//;
230 9         21 $data->($1);
231             }
232              
233 13 100       61 if (length($text)) {
234             # warn("re-parsing $text\n");
235 1         4 return $self->_format_line($text, $strong, $emphasized, $line, $link, $data);
236             }
237            
238 12         22 return undef;
239             }
240              
241             sub make_link {
242 3     3   8 my ($self, $link) = @_;
243              
244 3         4 my $title;
245 3         8 ($link, $title) = split(/\|/, $link, 2);
246 3   33     18 $title ||= $link;
247              
248 3         15 my $el = _element('link');
249 3         9 _add_attrib($el, href => $link);
250 3         8 $self->parent->start_element($el);
251 3         296 $self->parent->characters({Data => $title});
252 3         28 $self->parent->end_element(_element('link'));
253             }
254              
255             sub _element {
256 32     32   51 my ($name, $end) = @_;
257             return {
258 32 100       274 Name => $name,
259             LocalName => $name,
260             $end ? () : (Attributes => {}),
261             NamespaceURI => '',
262             Prefix => '',
263             };
264             }
265              
266             sub _add_attrib {
267 3     3   6 my ($el, $name, $value) = @_;
268            
269 3         17 $el->{Attributes}{"{}$name"} =
270             {
271             Name => $name,
272             LocalName => $name,
273             Prefix => "",
274             NamespaceURI => "",
275             Value => $value,
276             };
277             }
278              
279              
280              
281             1;
282             __END__