File Coverage

blib/lib/Pod/Elemental/Transformer/Splint.pm
Criterion Covered Total %
statement 184 207 88.8
branch 36 62 58.0
condition 10 23 43.4
subroutine 35 40 87.5
pod 0 8 0.0
total 265 340 77.9


line stmt bran cond sub pod time code
1 3     3   2812340 use 5.14.0;
  3         11  
2 3     3   16 use strict;
  3         7  
  3         74  
3 3     3   15 use warnings;
  3         6  
  3         193  
4              
5             package Pod::Elemental::Transformer::Splint;
6              
7             our $VERSION = '0.1100'; # VERSION
8             # ABSTRACT: Documentation from class metadata
9              
10 2     2   970 use Moose;
  2     1   472935  
  2         15  
  1         7900  
  1         10457  
  1         62  
11 2     2   15913 use Path::Tiny;
  2     1   20159  
  2         128  
  1         748  
  1         415  
  1         129  
12 2     2   1479 use Safe::Isa;
  2     1   820  
  2         260  
  1         6  
  1         1  
  1         55  
13 2     2   10 use Try::Tiny;
  2     1   5  
  2         107  
  1         673  
  1         1627  
  1         68  
14 2     2   1562 use List::UtilsBy 'extract_by';
  2     1   3348  
  2         139  
  1         793  
  1         63681  
  1         13  
15 2     2   1682 use Types::Standard qw/Str ArrayRef HashRef/;
  2     1   127556  
  2         25  
  1         1942  
  1         1033  
  1         6  
16 2     2   3604 use Module::Load qw/load/;
  2     1   2172  
  2         13  
  1         691  
  1         618  
  1         70  
17 2     2   1471 use Ref::Util qw/is_arrayref/;
  2     1   1247  
  2         154  
  1         74  
  1         2  
  1         8  
18 2     2   745 use lib 'lib';
  2     1   769  
  2         12  
  1         420  
  1         543971  
  1         22  
19              
20             with qw/Pod::Elemental::Transformer Pod::Elemental::Transformer::Splint::Util/;
21              
22             has command_name => (
23             is => 'rw',
24             isa => Str,
25             default => ':splint',
26             );
27             has default_type_library => (
28             is => 'rw',
29             isa => Str,
30             default => 'Types::Standard',
31             predicate => 'has_default_type_library',
32             );
33             has type_libraries => (
34             is => 'rw',
35             isa => HashRef,
36             traits => ['Hash'],
37             handles => {
38             get_library_for_type => 'get',
39             },
40             );
41             has classmeta => (
42             is => 'rw',
43             predicate => 'has_classmeta',
44             );
45             has attribute_renderer => (
46             is => 'rw',
47             isa => ArrayRef[HashRef[Str]],
48             traits => [qw/Array/],
49             default => sub {
50             [
51             { for => 'HTML', class => 'HtmlDefault' },
52             { for => 'markdown', class => 'HtmlDefault' },
53             ],
54             },
55             handles => {
56             all_attribute_renderers => 'elements',
57             }
58             );
59             has method_renderer => (
60             is => 'rw',
61             isa => ArrayRef[HashRef[Str]],
62             traits => [qw/Array/],
63             default => sub {
64             [
65             { for => 'HTML', class => 'HtmlDefault' },
66             { for => 'markdown', class => 'HtmlDefault' },
67             ],
68             },
69             handles => {
70             all_method_renderers => 'elements',
71             }
72             );
73              
74             around BUILDARGS => sub {
75             my $orig = shift;
76             my $class = shift;
77             my $args = shift;
78              
79             my $type_libraries = {};
80              
81             if(exists $args->{'type_libraries'}) {
82             my $lib = $args->{'type_libraries'};
83             $lib =~ s{([^\h]+=)}{---$1}g;
84             $lib =~ s{^---}{};
85             $lib =~ s{\h}{}g;
86             my @libraries = split /---/ => $lib;
87              
88             foreach my $librarydata (@libraries) {
89             my($library, $typesdata) = split /=/ => $librarydata;
90             my @types = split /,/ => $typesdata;
91              
92             foreach my $type (@types) {
93             $type_libraries->{ $type } = $library;
94             }
95             }
96             }
97             $args->{'type_libraries'} = $type_libraries;
98              
99             my $attribute_renderers = [];
100             my $method_renderers = [];
101              
102              
103             if(exists $args->{'attribute_renderer'}) {
104             my @renderers = split m{,\s+}, $args->{'attribute_renderer'};
105              
106             for my $renderer (@renderers) {
107             my($format, $class) = split m/=/, $renderer;
108             push @{ $attribute_renderers } => { for => $format, class => $class };
109             }
110             $args->{'attribute_renderer'} = $attribute_renderers;
111             }
112             if(exists $args->{'method_renderer'}) {
113             my @renderers = split m{,\s+}, $args->{'method_renderer'};
114              
115             for my $renderer (@renderers) {
116             my($format, $class) = split m/=/, $renderer;
117             $renderer = { for => $format, class => $class };
118             push @{ $method_renderers } => { for => $format, class => $class };
119             }
120             $args->{'method_renderer'} = $method_renderers;
121             }
122             $class->$orig($args);
123             };
124              
125             sub BUILD {
126 3     3 0 4663 my $self = shift;
127              
128 3         7 my $base = 'Pod::Elemental::Transformer::Splint';
129              
130             TYPE:
131 3         9 foreach my $type (qw/attribute method/) {
132 6         1132 my $all_method = sprintf 'all_%s_renderers', $type;
133              
134             RENDERER:
135 6         370 foreach my $renderer ($self->$all_method) {
136 12         2641 my $role = sprintf '%s::%sRenderer', $base, ucfirst $type;
137 12         42 my $classname = sprintf '%s::%s', $role, $renderer->{'class'};
138              
139             try {
140 12     12   478 load $classname;
141             }
142             catch {
143 0     0   0 die "Can't use $classname as renderer: $_";
144 12         103 };
145              
146 12 50       790 if(!$classname->does($role)) {
147 0         0 die "$classname doesn't do the $role role";
148             }
149              
150 12         2349 $renderer->{'renderer'} = $classname->new(for => $renderer->{'for'});
151             }
152             }
153             }
154              
155             sub transform_node {
156 2     2 0 19697 my $self = shift;
157 2         6 my $node = shift;
158              
159             CHILD:
160 2         5 foreach my $child (@{ $node->children }) {
  2         67  
161              
162 9         356 my $line_start = substr($child->content, 0 => length ($self->command_name) + 1);
163 9 100       407 next CHILD if $line_start ne sprintf '%s ', $self->command_name;
164              
165 5         198 my($prefix, $action, $param, $data) = split m/\h+/, $child->content, 4;
166              
167 5 100 66     90 if($action eq 'classname' && defined $param) {
168 2     2   205 eval "use $param";
  2         448  
  2         69366  
  2         31  
169 2 50       14 die "Can't use $param: $@" if $@;
170              
171 2         14 $self->classmeta($param->meta);
172 2         91 $child->content('');
173              
174 2         303 next CHILD;
175             }
176 3 50       169 next CHILD if !$self->has_classmeta;
177              
178 3 50 100     61 if($action eq 'attributes' && scalar $self->classmeta->get_attribute_list) {
179              
180 1         54 my @attributes = map { $self->classmeta->get_attribute($_) } $self->classmeta->get_attribute_list;
  1         52  
181              
182 1 50   1   17 my @unwanted = extract_by { $_->does('Documented') && !$_->documentation_order } @attributes;
  1         18  
183              
184 1 0   1   1563 my @custom_sort_order_attrs = sort { $a->documentation_order <=> $b->documentation_order || $a->name cmp $b->name } extract_by { $_->does('Documented') && $_->documentation_order < 1000 } @attributes;
  0 50       0  
  1         12  
185 1 0   0   284 my @docced_not_in_constr_attr = sort { $a->name cmp $b->name } extract_by { !defined $_->init_arg && $_->does('Documented') } @attributes;
  0         0  
  0         0  
186 1     0   16 my @not_in_constructor_attrs = sort { $a->name cmp $b->name } extract_by { !defined $_->init_arg } @attributes;
  0         0  
  0         0  
187 1     0   75 my @required_attrs = sort { $a->name cmp $b->name } extract_by { $_->is_required } @attributes;
  0         0  
  0         0  
188 1     0   15 my @documented_attrs = sort { $a->name cmp $b->name } extract_by { $_->does('Documented') } @attributes;
  0         0  
  0         0  
189 1         11 my @the_rest = sort { $a->name cmp $b->name } @attributes;
  0         0  
190              
191 1         4 my @wanted_attributes = (@custom_sort_order_attrs, @required_attrs, @documented_attrs, @the_rest, @docced_not_in_constr_attr, @not_in_constructor_attrs);
192             #* First attributes with documentation
193             #* then attributes available in constructor
194             #* then required attributes
195             #* and then alphabetical
196             #my @attribute_names = sort {
197             # ($a->does('Documented') && $a->has_documentation_order ? $a->documentation_order : 1000) <=> ($b->does('Documented') && $b->has_documentation_order ? $b->documentation_order : 1000)
198             # || ($b->init_arg // 0) <=> ($a->init_arg // 0)
199             # || ($b->is_required || 0) <=> ($a->is_required || 0)
200             # || $a->name cmp $b->name
201             # }
202             # map { $self->classmeta->get_attribute($_) }
203             # $self->classmeta->get_attribute_list;
204 1         2 my $content = '';
205              
206             ATTR:
207 1         3 foreach my $attr (@wanted_attributes) {
208 1 50 33     5 next ATTR if $attr->does('Documented') && $attr->has_documentation_order && $attr->documentation_order == 0;
      33        
209              
210 1         347 $content .= sprintf "\n=head2 %s\n", $attr->name;
211 1         5 my $prepared_attr = $self->prepare_attr($attr);
212 1         807 foreach my $attribute_renderer ($self->all_attribute_renderers) {
213 2         15 $content .= $attribute_renderer->{'renderer'}->render_attribute($prepared_attr);
214             }
215              
216             }
217 1         47 $child->content($content);
218             }
219              
220 3 100       292 if($action eq 'method') {
221 2 50       86 if(!$self->classmeta->has_method($param)) {
222 0         0 $child->content('');
223 0         0 return;
224             }
225              
226 2         292 my $method = $self->classmeta->get_method($param);
227 2         1235 my $content = sprintf "\n=head2 %s\n", $method->name;
228 2         11 my $prepared_method = $self->prepare_method($method);
229              
230 2         120 foreach my $method_renderer ($self->all_method_renderers) {
231 4         22 $content .= $method_renderer->{'renderer'}->render_method($prepared_method);
232             }
233 2         88 $child->content($content);
234              
235             }
236 3 50       498 if($action eq 'methods') {
237 0         0 my $content = '';
238              
239             METHOD:
240 0         0 foreach my $method_name ($self->classmeta->get_method_list) {
241 0         0 my $method = $self->classmeta->get_method($method_name);
242 0         0 $content = sprintf "\n=head2 %s\n", $method->name;
243 0         0 my $prepared_method = $self->prepare_method($method);
244              
245 0         0 foreach my $method_renderer ($self->all_method_renderers) {
246 0         0 $content .= $method_renderer->render_method($prepared_method);
247             }
248             }
249 0         0 $child->content($content);
250             }
251             }
252             }
253             sub prepare_attr {
254 1     1 0 2 my $self = shift;
255 1         2 my $attr = shift;
256              
257 1 50       34 my $settings = {
    50          
    50          
258             type => ($attr->type_constraint ? $self->make_type_string($attr->type_constraint) : undef),
259             required_text => $self->required_text($attr->is_required),
260             is_text => $self->is_text($attr),
261             default => $attr->default,
262             is_default_a_coderef => !!$attr->is_default_a_coderef(),
263             has_init_arg => defined $attr->init_arg ? 1 : 0,
264             documentation_default => $attr->does('Documented') ? $attr->documentation_default : undef,
265             };
266              
267 1         741 my $documentation_alts = [];
268 1 50 33     10 if($attr->does('Documented') && $attr->has_documentation_alts) {
269 1         601 my $documentation = $attr->documentation_alts;
270              
271 1         11 foreach my $key (sort grep { $_ ne '_' } keys %{ $documentation }) {
  2         13  
  1         7  
272 2         6 push @{ $documentation_alts } => [ $key, $documentation->{ $key } ];
  2         14  
273             }
274             }
275             return {
276 1 50 33     12 settings => $settings,
277             documentation_alts => $documentation_alts,
278             $attr->does('Documented') && $attr->has_documentation ? (documentation => $attr->documentation) : (),
279             };
280             }
281              
282             sub prepare_method {
283 2     2 0 5 my $self = shift;
284 2         4 my $method = shift;
285              
286 2         5 my $positional_params = [];
287 2         4 my $named_params = [];
288              
289 2         5 my $try_signature = undef;
290              
291             try {
292 2     2   104 $try_signature = $method->signature;
293             }
294 2     2   20 finally { };
295 2 50       102 return { map { $_ => [] } qw/positional_params named_params return_types/ } if !ref $try_signature;
  0         0  
296              
297 2         8 foreach my $param ($method->signature->positional_params) {
298             push @$positional_params => {
299             name => $param->name,
300 3         194 %{ $self->prepare_param($param) },
  3         10  
301             };
302             }
303 2 100       12 if($method->signature->has_slurpy) {
304 1         62 my $slurpy = $method->signature->slurpy_param;
305              
306             push @$positional_params => {
307             name => $slurpy->name,
308 1         68 %{ $self->prepare_param($slurpy) },
  1         4  
309             };
310             }
311              
312 2 0       76 foreach my $param (sort { $a->optional <=> $b->optional || $a->name cmp $b->name } $method->signature->named_params) {
  3         119  
313 3         17 my $name = $param->name;
314 3         12 $name =~ s{[\@\$\%]}{};
315             push @$named_params => {
316             name => $param->name,
317             name_without_sigil => $name,
318 3         10 %{ $self->prepare_param($param) },
  3         9  
319             };
320             }
321              
322 2         70 my $all_return_types = [];
323 2         9 foreach my $return_types ($method->signature->return_types) {
324              
325 2         115 foreach my $return_type (@$return_types) {
326 1 50       5 next if !$return_type->$_can('type');
327              
328 1         32 my($docs, $method_doc) = $self->get_docs($return_type);
329 1         15 push @$all_return_types => {
330             type => $self->make_type_string($return_type->type),
331             docs => $docs,
332             method_doc => $method_doc,
333             };
334             }
335             }
336              
337 2         9 my $data = {
338             positional_params => $positional_params,
339             named_params => $named_params,
340             return_types => $all_return_types,
341             };
342              
343 2         6 return $data;
344              
345             }
346              
347             sub get_docs {
348 8     8 0 10 my $self = shift;
349 8         13 my $thing = shift;
350              
351 8         10 my $docs = [];
352 8         14 my $method_doc = undef;
353              
354 8 50 33     70 if(exists $thing->traits->{'doc'} && ref $thing->traits->{'doc'} eq 'ARRAY') {
355 8         16 $docs = [ split /\n/ => join "\n" => @{ $thing->traits->{'doc'} } ];
  8         40  
356              
357 8 100       34 if(index ($docs->[-1], 'method_doc|') == 0) {
358 1         2 $method_doc = substr pop @{ $docs }, 11;
  1         3  
359             }
360             }
361 8         20 return ($docs, $method_doc);
362             }
363              
364             sub prepare_param {
365 7     7 0 10 my $self = shift;
366 7         22 my $param = shift;
367              
368 7         19 my($docs, $method_doc) = $self->get_docs($param);
369              
370             my $prepared = {
371             type => $self->make_type_string($param->type),
372             default => defined $param->default ? $param->default->() : undef,
373             default_when => $param->default_when,
374             has_default => defined $param->default ? 1 : 0,
375 7 100 33     39 traits => [ sort grep { $_ && $_ ne 'doc' && $_ ne 'optional' } ($param->traits, ($param->coerce ? 'coerce' : () ) ) ],
  7 100       115  
    50          
    50          
376             required_text => $self->required_text(!$param->optional),
377             is_required => !$param->optional,
378             method_doc => $method_doc,
379             docs => $docs,
380             };
381              
382 7         153 return $prepared;
383             }
384              
385             sub required_text {
386 8     8 0 57 my $self = shift;
387 8         17 my $value = shift;
388 8 100       42 return $value ? 'required' : 'optional';
389             }
390             sub is_text {
391 1     1 0 4 my $self = shift;
392 1         4 my $attr = shift;
393              
394 1 50       18 return $attr->has_write_method ? 'read/write' : 'read-only';
395             }
396              
397             1;
398              
399             __END__
400              
401             =pod
402              
403             =encoding UTF-8
404              
405             =head1 NAME
406              
407             Pod::Elemental::Transformer::Splint - Documentation from class metadata
408              
409              
410              
411             =begin HTML
412              
413             <p><img src="https://img.shields.io/badge/perl-5.14+-brightgreen.svg" alt="Requires Perl 5.14+" /> <a href="https://travis-ci.org/Csson/p5-Pod-Elemental-Transformer-Splint"><img src="https://api.travis-ci.org/Csson/p5-Pod-Elemental-Transformer-Splint.svg?branch=master" alt="Travis status" /></a></p>
414              
415             =end HTML
416              
417              
418             =begin markdown
419              
420             ![Requires Perl 5.14+](https://img.shields.io/badge/perl-5.14+-brightgreen.svg) [![Travis status](https://api.travis-ci.org/Csson/p5-Pod-Elemental-Transformer-Splint.svg?branch=master)](https://travis-ci.org/Csson/p5-Pod-Elemental-Transformer-Splint)
421              
422             =end markdown
423              
424             =head1 VERSION
425              
426             Version 0.1100, released 2016-01-12.
427              
428             =head1 SYNOPSIS
429              
430             # in weaver.ini
431             [-Transformer / Splint]
432             transformer = Splint
433              
434             =head1 DESCRIPTION
435              
436             Pod::Elemental::Transformer::Splint uses L<MooseX::AttributeDocumented> to add inlined documentation about attributes to pod.
437             If you write your classes with L<Moops> you can also document method signatures with L<Kavorka::TraitFor::Parameter::doc> (and L<::ReturnType::doc|Kavorka::TraitFor::ReturnType::doc>).
438              
439             A class defined like this:
440              
441             package My::Class;
442              
443             use Moose;
444              
445             has has_brakes => (
446             is => 'ro',
447             isa => Bool,
448             default => 1,
449             traits => ['Documented'],
450             documentation => 'Does the bike have brakes?',
451             documentation_alts => {
452             0 => 'Hopefully a track bike',
453             1 => 'Always nice to have',
454             },
455             );
456              
457             =pod
458              
459             :splint classname My::Class
460              
461             :splint attributes
462              
463             =cut
464              
465             Will render like this (to html):
466              
467             I<begin>
468              
469             =begin HTML
470              
471             <h2 id="has_brakes">has_brakes</h2>
472              
473             <table cellpadding="0" cellspacing="0">
474             <tr><td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;"><a href="https://metacpan.org/pod/Types::Standard#Bool">Bool</a></td>
475             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">optional, default: <code>1</code></td>
476             <td style="padding-right: 6px; padding-left: 6px; border-right: 1px solid #b8b8b8; white-space: nowrap;">read-only</td>
477             <td style="text-align: right; padding-right: 6px; padding-left: 6px;"><code>0</code>:</td>
478             <td style="padding-left: 12px;">Hopefully a track bike</td></tr><tr><td>&#160;</td>
479             <td>&#160;</td>
480             <td>&#160;</td>
481             <td style="text-align: right; padding-right: 6px; padding-left: 6px;"><code>1</code>:</td>
482             <td style="padding-left: 12px;">Always nice to have</td></tr>
483             </table><p>Does the bike have brakes?</p>
484              
485             =end HTML
486              
487             I<end>
488              
489             A L<Moops> class defined like this:
490              
491             class My::MoopsClass using Moose {
492              
493             ...
494              
495             method advanced_method(Int $integer does doc("Just an integer\nmethod_doc|This method is advanced."),
496             ArrayRef[Str|Bool] $lots_of_stuff does doc('It works with both types'),
497             Str :$name! does doc("What's the name"),
498             Int :$age does doc('The age of the thing') = 0,
499             Str :$pseudonym does doc('Incognito..')
500             --> Bool but assumed does doc('Did it succeed?')
501              
502             ) {
503             return 1;
504             }
505              
506             method less_advanced($stuff,
507             $another_thing does doc("Don't know what we get here"),
508             ArrayRef $the_remaining is slurpy does doc('All the remaining')
509             ) {
510             return 1;
511             }
512              
513             ...
514             }
515              
516             =pod
517              
518             :splint classname My::MoopsClass
519              
520             :splint method advanced_method
521              
522             It needs lots of documentation.
523              
524             :splint method less_advanced
525              
526             =cut
527              
528             Will render like this (to html):
529              
530             I<begin>
531              
532             =begin HTML
533              
534             <h2 id="advanced_method">advanced_method</h2>
535              
536              
537              
538             <p>This method is advanced.</p><table style="margin-bottom: 10px; margin-left: 10px; border-collapse: bollapse;" cellpadding="0" cellspacing="0">
539             <tr style="vertical-align: top;"><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">Positional parameters</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td></tr>
540             <tr style="vertical-align: top;">
541             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>$integer</code></td>
542             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#Int">Int</a></td>
543             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
544             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
545             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">Just an integer<br /></td>
546             </tr>
547             <tr style="vertical-align: top;">
548             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>$lots_of_stuff</code></td>
549             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a>[ <a href="https://metacpan.org/pod/Types::Standard#Str">Str</a> | <a href="https://metacpan.org/pod/Types::Standard#Bool">Bool</a> ]</td>
550             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
551             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
552             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">It works with both types<br /></td>
553             </tr>
554             <tr style="vertical-align: top;"><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">Named parameters</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td></tr>
555             <tr style="vertical-align: top;">
556             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>name =&gt; $value</code></td>
557             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#Str">Str</a></td>
558             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
559             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
560             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">What's the name</td>
561             </tr>
562             <tr style="vertical-align: top;">
563             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>age =&gt; $value</code></td>
564             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#Int">Int</a></td>
565             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">optional, default <code>= 0</code></td>
566             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
567             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">The age of the thing</td>
568             </tr>
569             <tr style="vertical-align: top;">
570             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>pseudonym =&gt; $value</code></td>
571             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#Str">Str</a></td>
572             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">optional, <span style="color: #999;">no default</span></td>
573             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
574             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">Incognito..</td>
575             </tr>
576             <tr style="vertical-align: top;"><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">Returns</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td></tr>
577             <tr style="vertical-align: top;">
578             <td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#Bool">Bool</a></td><td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;">&#160;</td><td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;">&#160;</td><td style="vertical-align: top; border-right: 1px solid #eee; padding: 3px 6px; border-bottom: 1px solid #eee;">&#160;</td>
579             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">Did it succeed?</td>
580             </tr>
581             </table>
582              
583             <p>It needs lots of documentation.</p>
584              
585             <h2 id="less_advanced">less_advanced</h2>
586              
587              
588              
589             <p></p><table style="margin-bottom: 10px; margin-left: 10px; border-collapse: bollapse;" cellpadding="0" cellspacing="0">
590             <tr style="vertical-align: top;"><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">Positional parameters</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td><td style="text-align: left; color: #444; background-color: #eee; font-weight: bold;">&#160;</td></tr>
591             <tr style="vertical-align: top;">
592             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>$stuff</code></td>
593             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"></td>
594             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
595             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
596             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;"></td>
597             </tr>
598             <tr style="vertical-align: top;">
599             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>$another_thing</code></td>
600             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"></td>
601             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
602             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; border-bottom: 1px solid #eee;"></td>
603             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">Don't know what we get here<br /></td>
604             </tr>
605             <tr style="vertical-align: top;">
606             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><code>$the_remaining</code></td>
607             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;"><a href="https://metacpan.org/pod/Types::Standard#ArrayRef">ArrayRef</a></td>
608             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">required</td>
609             <td style="vertical-align: top; border-right: 1px solid #eee; white-space: nowrap; padding: 3px 6px; border-bottom: 1px solid #eee;">slurpy</td>
610             <td style="padding: 3px 6px; vertical-align: top; border-bottom: 1px solid #eee;">All the remaining<br /></td>
611             </tr>
612             </table>
613              
614             =end HTML
615              
616             I<end>
617              
618             =head1 ATTRIBUTES
619              
620             The following settings are available in C<weaver.ini>:
621              
622             =head2 command_name
623              
624             Default: C<:splint>
625              
626             Defines the command used at the beginning of the line in pod.
627              
628             =head2 attribute_renderer
629              
630             Default: C<HTML=HtmlDefault, markdown=HtmlDefault>
631              
632             Define which renderers to use. Comma separated list of pairs where the key defines the format in pod and the value defines the renderer (in the C<Pod::Elemental::Transformer::Splint::AttributeRenderer> namespace).
633              
634             The default will render each attribute like this:
635              
636             =begin HTML
637              
638             <!-- attribute information -->
639              
640             =end HTML
641              
642             =begin markdown
643              
644             <!-- attribute information -->
645              
646             =end markdown
647              
648             =head2 method_renderer
649              
650             Default: C<HTML=HtmlDefault, markdown=HtmlDefault>
651              
652             Similar to L</attribute_renderer> but for methods. This is currently only assumed to work for methods defined with L<Kavorka> or L<Moops>.
653              
654             Method renderers are in the C<Pod::Elemental::Transformer::Splint::MethodRenderer> namespace.
655              
656             =head2 type_libraries
657              
658             Default: C<undef>
659              
660             If you use L<Type::Tiny> based type libraries, the types are usually linked to the correct library. Under some circumstances it might be necessary to specify which library a certain type
661             belongs to.
662              
663             It is a space separated list:
664              
665             type_libraries = Custom::Types=AType Types::Standard=Str,Int
666              
667             =head2 default_type_library
668              
669             Default: C<Types::Standard>
670              
671             The default Type::Tiny based type library to link types to.
672              
673             =head1 SEE ALSO
674              
675             =head1 SOURCE
676              
677             L<https://github.com/Csson/p5-Pod-Elemental-Transformer-Splint>
678              
679             =head1 HOMEPAGE
680              
681             L<https://metacpan.org/release/Pod-Elemental-Transformer-Splint>
682              
683             =head1 AUTHOR
684              
685             Erik Carlsson <info@code301.com>
686              
687             =head1 COPYRIGHT AND LICENSE
688              
689             This software is copyright (c) 2016 by Erik Carlsson.
690              
691             This is free software; you can redistribute it and/or modify it under
692             the same terms as the Perl 5 programming language system itself.
693              
694             =cut