File Coverage

blib/lib/Rubric/Entry/Formatter.pm
Criterion Covered Total %
statement 28 31 90.3
branch 9 16 56.2
condition n/a
subroutine 7 7 100.0
pod 1 1 100.0
total 45 55 81.8


line stmt bran cond sub pod time code
1 12     12   62 use strict;
  12         24  
  12         412  
2 12     12   66 use warnings;
  12         44  
  12         614  
3             package Rubric::Entry::Formatter;
4             # ABSTRACT: a base class for entry body formatters
5             $Rubric::Entry::Formatter::VERSION = '0.155';
6             # =head1 DESCRIPTION
7             #
8             # This class serves as a single point of dispatch for attempts to format entry
9             # bodies from their native format into rendered output.
10             #
11             # =cut
12              
13 12     12   99 use Carp ();
  12         105  
  12         193  
14 12     12   62 use Rubric::Config;
  12         131  
  12         124  
15              
16             # =head1 METHODS
17             #
18             # =head2 C< format >
19             #
20             # my $formatted = Rubric::Entry::Formatter->format(\%arg);
21             #
22             # This method accepts a set of named arguments and returns formatted output in
23             # the requested format. If it is unable to do so, it throws an exception.
24             #
25             # Valid arguments are:
26             #
27             # markup - the markup format used to mark up the text (default: _default)
28             # text - the text that has been marked up and should be formatted (required)
29             # format - the requested output format (required)
30             #
31             # Formatting requests are dispatched according to the configuration in
32             # C.
33             #
34             # =cut
35              
36             sub _load_formatter {
37 18     18   36 my ($class, $formatter) = @_;
38              
39 18 100       34 return 1 if eval { $formatter->can('as_text'); };
  18         309  
40              
41             ## no critic (StringyEval)
42 3 50       258 return 1 if eval qq{require $formatter};
43             ## use critic
44              
45 0         0 return 0;
46             }
47              
48             sub _formatter_for {
49 18     18   43 my ($class, $markup) = @_;
50              
51 18         97 my $markup_formatter = Rubric::Config->markup_formatter;
52 18 100       77 $markup_formatter->{_default} = 'Rubric::Entry::Formatter::Nil'
53             unless $markup_formatter->{_default};
54              
55 18 50       94 Carp::croak "no formatter is registered for $markup markup"
56             unless my $formatter = $markup_formatter->{ $markup };
57              
58 18         103 return $formatter;
59             }
60              
61             sub format {
62 18     18 1 1306 my ($class, $arg) = @_;
63 18         43 my $config = {}; # extra configuration for formatter code
64              
65 18         80 my $formatter = $class->_formatter_for($arg->{markup});
66              
67 18 50       61 if (ref $formatter) {
68 0         0 $config = { %$formatter };
69 0 0       0 Carp::croak "formatter config for $arg->{markup} includes no class"
70             unless $formatter = delete $config->{class};
71             }
72              
73 18 50       65 $class->_load_formatter($formatter)
74             or Carp::croak "couldn't load formatter '$formatter': $@";
75              
76 18 50       190 my $formatter_code = $formatter->can("as_$arg->{format}")
77             or Carp::croak "$formatter does not implement formatting to $arg->{format}";
78              
79 18         82 $formatter_code->($formatter, $arg, $config);
80             }
81              
82             # =head1 WRITING FORMATTERS
83             #
84             # Writing a formatter should be very simple; the interface is very simple,
85             # although it's also very young and so it may change when I figure out the
86             # problems in the current implementation.
87             #
88             # A formatter must implement an C method for each format to which it
89             # claims to be able to output formatted text. When Rubric::Entry::Formatter
90             # wants to dispatch text for formatting, it will call that method as follows:
91             #
92             # my $formatted = Formatter->as_whatever(\%arg);
93             #
94             # The arguments in C<%arg> will be the same as those passed to
95             # Rubric::Entry::Formatter.
96             #
97             # Actually, the method is found and called via C, so a suitably programmed
98             # module can respond to C to allow it to render into all the format it likes
99             # -- or at least to claim to.
100             #
101             # =cut
102              
103             1;
104              
105             __END__