File Coverage

blib/lib/Org/To/Base.pm
Criterion Covered Total %
statement 41 97 42.2
branch 31 70 44.2
condition 2 4 50.0
subroutine 8 12 66.6
pod 2 2 100.0
total 84 185 45.4


line stmt bran cond sub pod time code
1             package Org::To::Base;
2              
3 4     4   261587 use strict;
  4         7  
  4         163  
4 4     4   69 use 5.010001;
  4         13  
5 4     4   1600 use Log::ger;
  4         55  
  4         26  
6              
7 4     4   855 use List::Util qw(first);
  4         18  
  4         1528  
8 4     4   630 use Moo;
  4         8743  
  4         24  
9              
10             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
11             our $DATE = '2024-12-21'; # DATE
12             our $DIST = 'Org-To-HTML'; # DIST
13             our $VERSION = '0.237'; # VERSION
14              
15             has source_file => (is => 'rw'); # for informational purposes
16             has include_tags => (is => 'rw');
17             has exclude_tags => (is => 'rw');
18              
19             sub _included_children {
20 5     5   11 my ($self, $elem) = @_;
21              
22 5         20 my @htags = $elem->get_tags;
23 5   100     309 my @children = @{$elem->children // []};
  5         30  
24 5 50       20 if ($self->include_tags) {
25 0 0   0   0 if (!defined(first {my $tag=$_; grep {$_ eq $tag} @htags} @{$self->include_tags})) {
  0         0  
  0         0  
  0         0  
  0         0  
26             # headline doesn't contain include_tags, select only
27             # suheadlines that contain them
28 0         0 @children = ();
29 0   0     0 for my $c (@{ $elem->children // []}) {
  0         0  
30 0 0       0 next unless $c->isa('Org::Element::Headline');
31             my @hl_included = $elem->find(
32             sub {
33 0     0   0 my $el = shift;
34             return unless
35 0 0       0 $elem->isa('Org::Element::Headline');
36 0         0 my @t = $elem->get_tags;
37 0         0 return defined(first {my $tag=$_; grep {$_ eq $tag} @t}
  0         0  
  0         0  
38 0         0 @{$self->include_tags});
  0         0  
39 0         0 });
40 0 0       0 next unless @hl_included;
41 0         0 push @children, $c;
42             }
43 0 0       0 return () unless @children;
44             }
45             }
46 5 50       22 if ($self->exclude_tags) {
47 0     0   0 return () if defined(first {my $tag=$_; grep {$_ eq $tag} @htags}
  0         0  
  0         0  
48 0 0       0 @{$self->exclude_tags});
  0         0  
49             }
50 5         17 @children;
51             }
52              
53             sub export {
54 4     4 1 479677 my ($self, $doc) = @_;
55              
56 4         20 my $inct = $self->include_tags;
57 4 50       15 if ($inct) {
58 0         0 my $doc_has_include_tags;
59 0         0 for my $h ($doc->find('Org::Element::Headline')) {
60 0         0 my @htags = $h->get_tags;
61 0 0   0   0 if (defined(first {my $tag=$_; grep {$_ eq $tag} @htags} @$inct)) {
  0         0  
  0         0  
  0         0  
62 0         0 $doc_has_include_tags++;
63 0         0 last;
64             }
65             }
66 0 0       0 $self->include_tags(undef) unless $doc_has_include_tags;
67             }
68              
69 4         26 $self->export_elements($doc);
70             }
71              
72             sub export_elements {
73 18     18 1 45 my ($self, @elems) = @_;
74              
75 18         31 my $res = [];
76             ELEM:
77 18         36 for my $elem (@elems) {
78 21 50       80 if ($self->can("before_export_element")) {
79 21         57 $self->before_export_element(
80             hook => 'before_export_element',
81             elem => $elem,
82             );
83             }
84 21 50       170 if (log_is_trace) {
85 0         0 require String::Escape;
86 0         0 log_trace("exporting element %s (%s) ...", ref($elem),
87             String::Escape::elide(
88             String::Escape::printable($elem->as_string), 30));
89             }
90 21         102 my $elc = ref($elem);
91              
92 21 100       206 if ($elc eq 'Org::Element::Block') {
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
93 1         6 push @$res, $self->export_block($elem);
94             } elsif ($elc eq 'Org::Element::FixedWidthSection') {
95 1         5 push @$res, $self->export_fixed_width_section($elem);
96             } elsif ($elc eq 'Org::Element::Comment') {
97 0         0 push @$res, $self->export_comment($elem);
98             } elsif ($elc eq 'Org::Element::Drawer') {
99 0         0 push @$res, $self->export_drawer($elem);
100             } elsif ($elc eq 'Org::Element::Footnote') {
101 0         0 push @$res, $self->export_footnote($elem);
102             } elsif ($elc eq 'Org::Element::Headline') {
103 5         23 push @$res, $self->export_headline($elem);
104             } elsif ($elc eq 'Org::Element::List') {
105 0         0 push @$res, $self->export_list($elem);
106             } elsif ($elc eq 'Org::Element::ListItem') {
107 0         0 push @$res, $self->export_list_item($elem);
108             } elsif ($elc eq 'Org::Element::RadioTarget') {
109 0         0 push @$res, $self->export_radio_target($elem);
110             } elsif ($elc eq 'Org::Element::Setting') {
111 2         9 push @$res, $self->export_setting($elem);
112             } elsif ($elc eq 'Org::Element::Table') {
113 0         0 push @$res, $self->export_table($elem);
114             } elsif ($elc eq 'Org::Element::TableCell') {
115 0         0 push @$res, $self->export_table_cell($elem);
116             } elsif ($elc eq 'Org::Element::TableRow') {
117 0         0 push @$res, $self->export_table_row($elem);
118             } elsif ($elc eq 'Org::Element::TableVLine') {
119 0         0 push @$res, $self->export_table_vline($elem);
120             } elsif ($elc eq 'Org::Element::Target') {
121 0         0 push @$res, $self->export_target($elem);
122             } elsif ($elc eq 'Org::Element::Text') {
123 8         32 push @$res, $self->export_text($elem);
124             } elsif ($elc eq 'Org::Element::Link') {
125 0         0 push @$res, $self->export_link($elem);
126             } elsif ($elc eq 'Org::Element::TimeRange') {
127 0         0 push @$res, $self->export_time_range($elem);
128             } elsif ($elc eq 'Org::Element::Timestamp') {
129 0         0 push @$res, $self->export_timestamp($elem);
130             } elsif ($elc eq 'Org::Document') {
131 4         23 push @$res, $self->export_document($elem);
132             } else {
133 0         0 log_warn("Don't know how to export $elc element, skipped");
134 0 0       0 push @$res, $self->export_elements(@{$elem->children})
  0         0  
135             if $elem->children;
136             }
137              
138 21 50       257 if ($self->can("after_export_element")) {
139 0         0 $self->after_export_element(
140             hook => 'after_export_element',
141             elem => $elem,
142             );
143             }
144             }
145              
146 18         106 join "", @$res;
147             }
148              
149             1;
150             # ABSTRACT: Base class for Org exporters
151              
152             __END__
153              
154             =pod
155              
156             =encoding UTF-8
157              
158             =head1 NAME
159              
160             Org::To::Base - Base class for Org exporters
161              
162             =head1 VERSION
163              
164             This document describes version 0.237 of Org::To::Base (from Perl distribution Org-To-HTML), released on 2024-12-21.
165              
166             =head1 SYNOPSIS
167              
168             # Not to be used directly. Use one of its subclasses, like Org::To::HTML.
169              
170             =head1 DESCRIPTION
171              
172             This module is a base class for Org exporters. To create an exporter, subclass
173             from this class (as well as add L<Org::To::Role> role) and provide an
174             implementation for the export_*() methods. Add extra attributes for export
175             options as necessary (for example, Org::To::HTML adds C<html_title>, C<css_url>,
176             and so on).
177              
178             =for Pod::Coverage BUILD
179              
180             =head1 ATTRIBUTES
181              
182             =head2 include_tags
183              
184             Arrayref. Works like Org's 'org-export-select-tags' variable. If the whole
185             document doesn't have any of these tags, then the whole document will be
186             exported. Otherwise, trees that do not carry one of these tags will be excluded.
187             If a selected tree is a subtree, the heading hierarchy above it will also be
188             selected for export, but not the text below those headings.
189              
190             =head2 exclude_tags
191              
192             Arrayref. If the whole document doesn't have any of these tags, then the whole
193             document will be exported. Otherwise, trees that do not carry one of these tags
194             will be excluded. If a selected tree is a subtree, the heading hierarchy above
195             it will also be selected for export, but not the text below those headings.
196              
197             C<exclude_tags> is evaluated after L</include_tags>.
198              
199             =head2 source_file
200              
201             String. Optional. Can be set for informational purposes, e.g. will be used as
202             default title when document does not set C>#+TITLE>.
203              
204             =head1 METHODS
205              
206             =head2 $exp->export($doc) => STR
207              
208             Export Org.
209              
210             =head2 $exp->export_elements(@elems) => STR
211              
212             Export Org element objects and with the children, recursively. Will call various
213             C<export_*()> methods according to element class. Should return a string which
214             is the exported document.
215              
216             Several hooks are recognized and will be invoked if defined:
217              
218             =over
219              
220             =item * before_export_element
221              
222             Will be called before calling each C<export_*()>. Will be passed hash argument
223             C<%hash> containing these keys: C<hook> (hook name, in this case
224             C<before_export_element>), C<elem> (the element object).
225              
226             =item * after_export_element
227              
228             Will be called after calling each C<export_*()>. Will be passed hash argument
229             C<%hash> containing these keys: C<hook> (hook name, in this case
230             C<after_export_element>), C<elem> (the element object).
231              
232             =back
233              
234             =head1 HOMEPAGE
235              
236             Please visit the project's homepage at L<https://metacpan.org/release/Org-To-HTML>.
237              
238             =head1 SOURCE
239              
240             Source repository is at L<https://github.com/perlancar/perl-Org-To-HTML>.
241              
242             =head1 AUTHOR
243              
244             perlancar <perlancar@cpan.org>
245              
246             =head1 CONTRIBUTING
247              
248              
249             To contribute, you can send patches by email/via RT, or send pull requests on
250             GitHub.
251              
252             Most of the time, you don't need to build the distribution yourself. You can
253             simply modify the code, then test via:
254              
255             % prove -l
256              
257             If you want to build the distribution (e.g. to try to install it locally on your
258             system), you can install L<Dist::Zilla>,
259             L<Dist::Zilla::PluginBundle::Author::PERLANCAR>,
260             L<Pod::Weaver::PluginBundle::Author::PERLANCAR>, and sometimes one or two other
261             Dist::Zilla- and/or Pod::Weaver plugins. Any additional steps required beyond
262             that are considered a bug and can be reported to me.
263              
264             =head1 COPYRIGHT AND LICENSE
265              
266             This software is copyright (c) 2024 by perlancar <perlancar@cpan.org>.
267              
268             This is free software; you can redistribute it and/or modify it under
269             the same terms as the Perl 5 programming language system itself.
270              
271             =head1 BUGS
272              
273             Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=Org-To-HTML>
274              
275             When submitting a bug or request, please include a test-file or a
276             patch to an existing test-file that illustrates the bug or desired
277             feature.
278              
279             =cut