File Coverage

lib/APISchema/Generator/Markdown/Formatter.pm
Criterion Covered Total %
statement 89 97 91.7
branch 36 48 75.0
condition 6 6 100.0
subroutine 21 21 100.0
pod 0 12 0.0
total 152 184 82.6


line stmt bran cond sub pod time code
1             package APISchema::Generator::Markdown::Formatter;
2 3     3   46 use 5.014;
  3         13  
3 3     3   12 use strict;
  3         4  
  3         59  
4 3     3   12 use warnings;
  3         4  
  3         93  
5              
6             # core
7 3     3   12 use Exporter qw(import);
  3         6  
  3         141  
8             our @EXPORT = qw(type json pretty_json code restriction desc anchor method methods content_type http_status http_status_code);
9              
10             # cpan
11 3     3   850 use HTTP::Status qw(status_message);
  3         11195  
  3         423  
12 3     3   635 use URI::Escape qw(uri_escape_utf8);
  3         2377  
  3         163  
13 3     3   21 use JSON::XS ();
  3         7  
  3         158  
14             my $JSON = JSON::XS->new->canonical(1);
15              
16             use constant +{
17 3         3229 RESTRICTIONS => [qw(required max_items min_items max_length min_length maximum minimum pattern)],
18             SHORT_DESCRIPTION_LENGTH => 100,
19 3     3   15 };
  3         6  
20              
21             sub type ($) {
22 75     75 0 3590 my $def = shift;
23 75         117 my $bar = '|';
24              
25 75 100       185 my $ref = ref $def ? $def->{'$ref'} : $def;
26 75 100       165 if ($ref) {
27 21         51 $ref = $ref =~ s!^#/resource/!!r;
28 21         54 my $ref_text = "`$ref`";
29 21         46 my $name = $ref =~ s!/.*$!!r;
30 21 50       65 $ref_text = sprintf('[%s](#%s)', $ref_text, anchor(resource => $name)) if $name;
31 21         892 return $ref_text;
32             }
33              
34 54         94 my $type = $def->{type};
35 54 100       109 if ($type) {
36 51 50       1148 return sprintf '`%s`', $type unless ref $type;
37 0 0       0 return join $bar, map { code($_) } @{$type} if ref $type eq 'ARRAY';
  0         0  
  0         0  
38             }
39              
40 3 50       10 return join $bar, map { code($_) } @{$def->{enum}} if $def->{enum};
  8         18  
  3         62  
41              
42 0         0 return 'undefined';
43             }
44              
45             sub json ($) {
46 54     54 0 94 my $x = shift;
47 54 100       151 if (ref $x eq 'SCALAR') {
    100          
48 1 50       6 if ($$x eq 1) {
    0          
49 1         3 $x = 'true';
50             } elsif ($$x eq 0) {
51 0         0 $x = 'false';
52             }
53             } elsif (ref $x) {
54 24         250 $x = $JSON->encode($x);
55             } else {
56 29         132 $x = $JSON->encode([$x]);
57 29         205 $x =~ s/^\[(.*)\]$/$1/;
58             }
59 54         500 return $x;
60             }
61              
62             my $PRETTY_JSON = JSON::XS->new->canonical(1)->indent(1)->pretty(1);
63             sub pretty_json ($) {
64 18     18 0 44 my $x = shift;
65 18 100       52 if (ref $x) {
66 16         229 $x = $PRETTY_JSON->encode($x);
67             } else {
68 2         9 $x = $PRETTY_JSON->encode([$x]);
69 2         16 $x =~ s/^\[\s*(.*)\s*\]\n$/$1/;
70             }
71 18         431 return $x;
72             }
73              
74             sub _code ($) {
75 71     71   133 my $text = shift;
76 71 100       301 return '' unless defined $text;
77 63 50       186 if ($text =~ /[`|]/) {
78 0         0 $text =~ s/[|]/|/g;
79 0         0 return sprintf '%s', $text;
80             }
81 63         1179 return sprintf '`%s`', $text;
82             }
83              
84             sub code ($) {
85 86     86 0 864 my $text = shift;
86 86 100       1105 return '' unless defined $text;
87 32         60 return _code json $text;
88             }
89              
90             sub anchor ($$) {
91 75     75 0 3915 my ($label, $obj) = @_;
92 75 100       216 my $name = ref $obj ? $obj->title : $obj;
93 75         312 return sprintf '%s-%s', $label, uri_escape_utf8($name);
94             }
95              
96             sub restriction ($) {
97 39     39 0 368 my $def = shift;
98 39 50       101 return '' unless (ref $def) eq 'HASH';
99              
100 39         72 my @result = ();
101 39         53 for my $r (sort @{+RESTRICTIONS}) {
  39         246  
102 312 100       604 next unless defined $def->{$r};
103              
104 9 50       32 if (ref $def->{$r}) {
105 9         37 push @result, _code sprintf "$r%s", json $def->{$r};
106             } else {
107 0         0 push @result, _code sprintf "$r(%s)", json $def->{$r};
108             }
109             }
110 39         804 return join ' ', @result;
111             }
112              
113             sub desc ($) {
114 39   100 39 0 431 my $text = shift || '';
115 39         97 $text = $text =~ s/[\r\n].*\z//sr;
116 39 50       101 $text = substr($text, 0, SHORT_DESCRIPTION_LENGTH) . '...'
117             if length($text) > SHORT_DESCRIPTION_LENGTH;
118 39         723 return $text;
119             }
120              
121             sub method ($) {
122 9     9 0 506 my $method = shift;
123 9 100 100     66 return $method->[0] if (ref $method || '') eq 'ARRAY';
124 8         167 return $method;
125             }
126              
127             sub methods ($) {
128 18     18 0 1287 my $method = shift;
129 18 100 100     116 return join ', ', map { _code($_) } @$method
  4         8  
130             if (ref $method || '') eq 'ARRAY';
131 16         47 return _code($method);
132             }
133              
134             sub content_type ($) {
135 30     30 0 295 my $type = shift;
136 30 100       343 return '-' unless length($type);
137 15         286 return "`$type`";
138             }
139              
140             sub http_status ($) {
141 19     19 0 793 my $code = shift;
142 19 100       67 return undef unless $code;
143 11         49 return join(' ', $code, status_message($code));
144             }
145              
146             sub http_status_code {
147 10     10 0 269 return _code http_status shift;
148             }
149              
150             1;