File Coverage

blib/lib/Text/Md2Inao/Util.pm
Criterion Covered Total %
statement 62 71 87.3
branch 16 16 100.0
condition 2 3 66.6
subroutine 11 12 91.6
pod 0 5 0.0
total 91 107 85.0


line stmt bran cond sub pod time code
1             package Text::Md2Inao::Util;
2 29     29   741 use utf8;
  29         54  
  29         263  
3 29     29   830 use strict;
  29         47  
  29         1008  
4 29     29   161 use warnings;
  29         51  
  29         1182  
5              
6 29     29   11830 use Exporter::Lite;
  29         9083  
  29         210  
7 29     29   29726 use Unicode::EastAsianWidth;
  29         20284  
  29         4048  
8              
9 29     29   179 use Text::Md2Inao::Logger;
  29         56  
  29         9218  
10              
11             our @EXPORT = qw/
12             to_list_style
13             visual_length
14             replace_note_parenthesis
15             fallback_to_html
16             Dumper
17             /;
18              
19             # 本文中に(◯1)や(1)など、リストを参照するときの形式に変換する
20             # 「リスト1.1(c1)を見てください」
21             # ->
22             # 「リスト1.1(◯1)を見てください」となる
23             #
24             # (d1) -> (1) # desc
25             # (c1) -> (◯1) # circle
26             # (s1) -> [1] # square
27             # (a1) -> (a) # alpha
28             #
29             # エスケープも可能
30             # (\d1) -> (d1)
31             # (\c1) -> (c1)
32             sub to_list_style {
33 296     296 0 384     my $text = shift;
34              
35             # convert
36 296         534     $text =~ s/\(d(\d+)\)/($1)/g;
37 296         532     $text =~ s/\(c(\d+)\)/(○$1)/g;
38 296         477     $text =~ s/\(s(\d+)\)/[$1]/g;
39 296         464     $text =~ s/\(a(\d+)\)/'(' . chr($1 + 96) . ')'/ge;
  14         65  
40              
41             # escape
42 296         1230     $text =~ s/\(\\([dcsa]?\d+)\)/($1)/g;
43              
44 296         892     return $text;
45             }
46              
47             # 文字幅計算
48             # http://d.hatena.ne.jp/tokuhirom/20070514/1179108961
49             sub visual_length {
50 151     151 0 220     local $_ = shift;
51 151         177     my $ret = 0;
52 29 100   29   170     while (/(?:(\p{InFullwidth}+)|(\p{InHalfwidth}+))/g) { $ret += ($1 ? length($1)*2 : length($2)) }
  29         49  
  29         451  
  151         833  
  327         33582  
53 151         1292     return $ret;
54             }
55              
56             # 脚注記法への変換
57             # (注: ... ) → ◆注/◆ ... ◆/注◆
58             # 入れ子の括弧も考慮る
59             sub replace_note_parenthesis {
60 34     34 0 141     my ($context, $line, $label) = @_;
61 34         56     my @end_pos;
62              
63             ## 1文字ずつ追って括弧の対応を調べる
64 34         536     my @char = split //, $line;
65 34         99     my $level = 0;
66 34         50     my $index = 0;
67              
68 34         78     for (@char) {
69 1615 100       3751         if ($_ eq '(') {
70 76 100 66     370             if ($char[$index + 1] eq '注' and $char[$index + 2] eq ':') {
71 36         121                 $context->in_footnote(1);
72                         }
73 76 100       346             if ($context->in_footnote) {
74 41         198                 $level++;
75                         }
76                     }
77 1615 100       2538         if ($_ eq ')') {
78 76 100       196             if ($context->in_footnote) {
79             ## $in_footnote && $level == 0
80             ## (注: _italic_ ) とかで中で $line が分断されたケース
81 41 100       265                 if ($level == 0) {
    100          
82 5         12                     push @end_pos, $index;
83 5         20                     $context->in_footnote(0);
84                             }
85             ## 普通に (注: の対応括弧が見つかった
86                             elsif ($level == 1) {
87 31         119                     push @end_pos, $index;
88 31         43                     $level = 0;
89 31         85                     $context->in_footnote(0);
90                             }
91              
92             ## (注: の中に入れ子になっている括弧の対応括弧が見つかった
93                             else {
94 5         11                     $level--;
95                             }
96                         }
97                     }
98 1615         1951         $index++;
99                 }
100              
101             ## 前から置換してくと置換後文字のが文字数多くて位置がずれるので後ろから
102 34         81     for my $pos (reverse @end_pos) {
103 36         233         substr $line, $pos, 1, "◆/$label◆";
104                 }
105              
106 34         294     $line =~ s!\(注:!◆$label/◆!g;
107 34         267     return $line;
108             }
109              
110             sub fallback_to_html {
111 10     10 0 19     my $h = shift;
112 10         32     log warn => sprintf "HTMLタグは `<%s>` もしくは実体参照でエスケープしてください。しない場合の出力は不定です", $h->tag;
113 10         55     return $h->as_HTML('', '', {});
114             }
115              
116             sub Dumper {
117 0     0 0       require Data::Recursive::Encode;
118 0               require Data::Dumper;
119 0               my $dd = Data::Dumper->new([map { Data::Recursive::Encode->encode_utf8($_) } @_]);
  0            
120 0               $dd->Indent(1);
121 0               $dd->Useqq(0);
122 0               $dd->Sortkeys(1);
123 0               $dd->Terse(1);
124 0               return $dd->Dump();
125             }
126              
127             1;
128