blib/lib/Text/Xatena.pm | |||
---|---|---|---|
Criterion | Covered | Total | % |
statement | 78 | 79 | 98.7 |
branch | 19 | 22 | 86.3 |
condition | 6 | 8 | 75.0 |
subroutine | 15 | 15 | 100.0 |
pod | 1 | 3 | 33.3 |
total | 119 | 127 | 93.7 |
line | stmt | bran | cond | sub | pod | time | code |
---|---|---|---|---|---|---|---|
1 | package Text::Xatena; | ||||||
2 | |||||||
3 | 20 | 20 | 808703 | use strict; | |||
20 | 50 | ||||||
20 | 717 | ||||||
4 | 20 | 20 | 102 | use warnings; | |||
20 | 38 | ||||||
20 | 529 | ||||||
5 | 20 | 20 | 3495 | use UNIVERSAL::require; | |||
20 | 6744 | ||||||
20 | 191 | ||||||
6 | |||||||
7 | 20 | 20 | 8630 | use Text::Xatena::LineScanner; | |||
20 | 59 | ||||||
20 | 223 | ||||||
8 | 20 | 20 | 8086 | use Text::Xatena::Node; | |||
20 | 67 | ||||||
20 | 265 | ||||||
9 | 20 | 20 | 10640 | use Text::Xatena::Node::Root; | |||
20 | 53 | ||||||
20 | 161 | ||||||
10 | 20 | 20 | 7915 | use Text::Xatena::Inline; | |||
20 | 61 | ||||||
20 | 157 | ||||||
11 | 20 | 20 | 150 | use Text::Xatena::Util; | |||
20 | 41 | ||||||
20 | 172 | ||||||
12 | |||||||
13 | our $VERSION = '0.18'; | ||||||
14 | |||||||
15 | our $SYNTAXES = [ | ||||||
16 | 'Text::Xatena::Node::SeeMore', | ||||||
17 | 'Text::Xatena::Node::SuperPre', | ||||||
18 | 'Text::Xatena::Node::StopP', | ||||||
19 | 'Text::Xatena::Node::Blockquote', | ||||||
20 | 'Text::Xatena::Node::Pre', | ||||||
21 | 'Text::Xatena::Node::List', | ||||||
22 | 'Text::Xatena::Node::DefinitionList', | ||||||
23 | 'Text::Xatena::Node::Table', | ||||||
24 | 'Text::Xatena::Node::Section', | ||||||
25 | 'Text::Xatena::Node::Comment', | ||||||
26 | ]; | ||||||
27 | |||||||
28 | sub new { | ||||||
29 | 103 | 103 | 0 | 1655 | my ($class, %opts) = @_; | ||
30 | |||||||
31 | 103 | 410 | my $self = bless { %opts }, $class; | ||||
32 | |||||||
33 | 103 | 100 | 658 | $self->{templates} ||= {}; | |||
34 | 2 | 50 | 9 | $self->{templates} = { | |||
35 | map { | ||||||
36 | 103 | 360 | my $pkg = $_ =~ /::/ ? $_ : "Text::Xatena::Node::$_"; | ||||
37 | 2 | 9 | $pkg => $self->{templates}->{$_}; | ||||
38 | } | ||||||
39 | 103 | 161 | keys %{ $self->{templates} } | ||||
40 | }; | ||||||
41 | |||||||
42 | 1011 | 100 | 3080 | $self->{syntaxes} = [ | |||
43 | map { | ||||||
44 | 103 | 100 | 504 | my $pkg = $_ =~ /::/ ? $_ : "Text::Xatena::Node::$_"; | |||
45 | 1011 | 50 | 6119 | $pkg->use or die $@; | |||
46 | 1011 | 7604 | $pkg; | ||||
47 | } | ||||||
48 | 103 | 227 | @{ $opts{syntaxes} || $SYNTAXES } | ||||
49 | ]; | ||||||
50 | |||||||
51 | 103 | 66 | 1298 | $self->{inline} ||= Text::Xatena::Inline->new; | |||
52 | |||||||
53 | 103 | 376 | $self; | ||||
54 | } | ||||||
55 | |||||||
56 | sub format { | ||||||
57 | 107 | 107 | 0 | 601 | my ($self, $string, %opts) = @_; | ||
58 | 107 | 1003 | $string =~ s{\r\n?|\n}{\n}g; | ||||
59 | |||||||
60 | 107 | 100 | 337 | $self->inline($opts{inline}) if $opts{inline}; | |||
61 | |||||||
62 | 107 | 100 | 309 | if ($self->{hatena_compatible}) { | |||
63 | 9 | 28 | $self->{templates}->{'Text::Xatena::Node::Section'} = q[ | ||||
64 | |
||||||
65 | {{= $content }} | ||||||
66 | ]; | ||||||
67 | |||||||
68 | 20 | 20 | 9128 | no warnings "once", "redefine"; | |||
20 | 47 | ||||||
20 | 11140 | ||||||
69 | local *Text::Xatena::Node::as_html_paragraph = sub { | ||||||
70 | 14 | 14 | 33 | my ($self, $context, $text, %opts) = @_; | |||
71 | 14 | 33 | $text = $context->inline->format($text, %opts); | ||||
72 | |||||||
73 | 14 | 38 | $text =~ s{\n$}{}g; | ||||
74 | 14 | 50 | 101 | if ($opts{stopp}) { | |||
75 | 0 | 0 | $text; | ||||
76 | } else { | ||||||
77 | " " . join("", |
||||||
78 | map { | ||||||
79 | 14 | 100 | 47 | if (/^(\n+)$/) { | |||
26 | 61 | ||||||
80 | 6 | 29 | "" . (" \n" x (length($1) - 2)) . " "; |
||||
81 | } else { | ||||||
82 | 20 | 94 | $_; | ||||
83 | } | ||||||
84 | } | ||||||
85 | split(/(\n+)/, $text) | ||||||
86 | ) . "\n"; | ||||||
87 | } | ||||||
88 | 9 | 71 | }; | ||||
89 | |||||||
90 | 9 | 31 | $self->_parse($string)->as_html($self); | ||||
91 | } else { | ||||||
92 | 98 | 306 | $self->_parse($string)->as_html($self); | ||||
93 | } | ||||||
94 | } | ||||||
95 | |||||||
96 | sub inline { | ||||||
97 | 250 | 250 | 1 | 343 | my ($self, $new) = @_; | ||
98 | 250 | 100 | 567 | if (@_ > 1) { | |||
99 | 1 | 4 | $self->{inline} = $new; | ||||
100 | } else { | ||||||
101 | 249 | 2189 | $self->{inline}; | ||||
102 | } | ||||||
103 | } | ||||||
104 | |||||||
105 | sub _parse { | ||||||
106 | 120 | 120 | 367 | my ($self, $string) = @_; | |||
107 | |||||||
108 | 120 | 177 | my @syntaxes = @{ $self->{syntaxes} }; | ||||
120 | 599 | ||||||
109 | 120 | 817 | my $s = Text::Xatena::LineScanner->new($string); | ||||
110 | 120 | 800 | my $root = Text::Xatena::Node::Root->new ; | ||||
111 | 120 | 284 | my $stack = [ $root ]; | ||||
112 | 120 | 450 | loop: until ($s->eos) { | ||||
113 | 388 | 662 | my $parent = $stack->[-1]; | ||||
114 | |||||||
115 | 388 | 634 | for my $pkg (@syntaxes) { | ||||
116 | 3286 | 100 | 14806 | $pkg->parse($s, $parent, $stack) and next loop; | |||
117 | } | ||||||
118 | |||||||
119 | # plain lines | ||||||
120 | 250 | 7957 | push @$parent, $s->next; | ||||
121 | } | ||||||
122 | |||||||
123 | 120 | 1424 | $root; | ||||
124 | } | ||||||
125 | |||||||
126 | sub _tmpl { | ||||||
127 | 100 | 100 | 223 | my ($self, $pkg, $default, $stash) = @_; | |||
128 | 100 | 207 | my $tmpl = $self->{templates}->{$pkg}; | ||||
129 | 100 | 100 | 66 | 749 | my $sub = ref($tmpl) eq 'CODE' ? $tmpl : template($tmpl || $default, [ keys %$stash ]); | ||
130 | 100 | 342 | $self->{templates}->{$pkg} = $sub; | ||||
131 | 100 | 1811 | $sub->($stash); | ||||
132 | } | ||||||
133 | |||||||
134 | 1; | ||||||
135 | __END__ |