File Coverage

blib/lib/Pod/Elemental/Transformer/Splint.pm
Criterion Covered Total %
statement 107 183 58.4
branch 20 62 32.2
condition 7 23 30.4
subroutine 22 32 68.7
pod 0 8 0.0
total 156 308 50.6


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