• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# makeinfo HTML output init file
2#
3# Copyright (c) 2011, 2012 Free Software Foundation, Inc.
4# Copyright (c) 2014 Andreas Cadhalpun
5# Copyright (c) 2014 Tiancheng "Timothy" Gu
6#
7# This file is part of FFmpeg.
8#
9# FFmpeg is free software; you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation; either version 3 of the License, or
12# (at your option) any later version.
13#
14# FFmpeg is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17# General Public License for more details.
18#
19# You should have received a copy of the GNU General Public
20# License along with FFmpeg; if not, write to the Free Software
21# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
23# Texinfo 7.0 changed the syntax of various functions.
24# Provide a shim for older versions.
25sub ff_set_from_init_file($$) {
26    my $key = shift;
27    my $value = shift;
28    if (exists &{'texinfo_set_from_init_file'}) {
29        texinfo_set_from_init_file($key, $value);
30    } else {
31        set_from_init_file($key, $value);
32    }
33}
34
35sub ff_get_conf($) {
36    my $key = shift;
37    if (exists &{'texinfo_get_conf'}) {
38        texinfo_get_conf($key);
39    } else {
40        get_conf($key);
41    }
42}
43
44sub get_formatting_function($$) {
45    my $obj = shift;
46    my $func = shift;
47
48    my $sub = $obj->can('formatting_function');
49    if ($sub) {
50        return $obj->formatting_function($func);
51    } else {
52        return $obj->{$func};
53    }
54}
55
56# determine texinfo version
57my $program_version_num = version->declare(ff_get_conf('PACKAGE_VERSION'))->numify;
58my $program_version_6_8 = $program_version_num >= 6.008000;
59
60# no navigation elements
61ff_set_from_init_file('HEADERS', 0);
62
63sub ffmpeg_heading_command($$$$$)
64{
65    my $self = shift;
66    my $cmdname = shift;
67    my $command = shift;
68    my $args = shift;
69    my $content = shift;
70
71    my $result = '';
72
73    # not clear that it may really happen
74    if ($self->in_string) {
75        $result .= $self->command_string($command) ."\n" if ($cmdname ne 'node');
76        $result .= $content if (defined($content));
77        return $result;
78    }
79
80    my $element_id = $self->command_id($command);
81    $result .= "<a name=\"$element_id\"></a>\n"
82        if (defined($element_id) and $element_id ne '');
83
84    print STDERR "Process $command "
85        .Texinfo::Structuring::_print_root_command_texi($command)."\n"
86            if ($self->get_conf('DEBUG'));
87    my $element;
88    if ($Texinfo::Common::root_commands{$command->{'cmdname'}}
89        and $command->{'parent'}
90        and $command->{'parent'}->{'type'}
91        and $command->{'parent'}->{'type'} eq 'element') {
92        $element = $command->{'parent'};
93    }
94    if ($element) {
95        $result .= &{get_formatting_function($self, 'format_element_header')}($self, $cmdname,
96                                                       $command, $element);
97    }
98
99    my $heading_level;
100    # node is used as heading if there is nothing else.
101    if ($cmdname eq 'node') {
102        if (!$element or (!$element->{'extra'}->{'section'}
103            and $element->{'extra'}->{'node'}
104            and $element->{'extra'}->{'node'} eq $command
105             # bogus node may not have been normalized
106            and defined($command->{'extra'}->{'normalized'}))) {
107            if ($command->{'extra'}->{'normalized'} eq 'Top') {
108                $heading_level = 0;
109            } else {
110                $heading_level = 3;
111            }
112        }
113    } else {
114        $heading_level = $command->{'level'};
115    }
116
117    my $heading = $self->command_text($command);
118    # $heading not defined may happen if the command is a @node, for example
119    # if there is an error in the node.
120    if (defined($heading) and $heading ne '' and defined($heading_level)) {
121
122        if ($Texinfo::Common::root_commands{$cmdname}
123            and $Texinfo::Common::sectioning_commands{$cmdname}) {
124            my $content_href = $self->command_contents_href($command, 'contents',
125                                                            $self->{'current_filename'});
126            if ($content_href) {
127                my $this_href = $content_href =~ s/^\#toc-/\#/r;
128                $heading .= '<span class="pull-right">'.
129                              '<a class="anchor hidden-xs" '.
130                                 "href=\"$this_href\" aria-hidden=\"true\">".
131            ($ENV{"FA_ICONS"} ? '<i class="fa fa-link"></i>'
132                              : '#').
133                              '</a> '.
134                              '<a class="anchor hidden-xs"'.
135                                 "href=\"$content_href\" aria-hidden=\"true\">".
136            ($ENV{"FA_ICONS"} ? '<i class="fa fa-navicon"></i>'
137                              : 'TOC').
138                              '</a>'.
139                            '</span>';
140            }
141        }
142
143        if ($self->in_preformatted()) {
144            $result .= $heading."\n";
145        } else {
146            # if the level was changed, set the command name right
147            if ($cmdname ne 'node'
148                and $heading_level ne $Texinfo::Common::command_structuring_level{$cmdname}) {
149                $cmdname
150                    = $Texinfo::Common::level_to_structuring_command{$cmdname}->[$heading_level];
151            }
152            # format_heading_text expects an array of headings for texinfo >= 7.0
153            if ($program_version_num >= 7.000000) {
154                $heading = [$heading];
155            }
156            $result .= &{get_formatting_function($self,'format_heading_text')}(
157                        $self, $cmdname, $heading,
158                        $heading_level +
159                        $self->get_conf('CHAPTER_HEADER_LEVEL') - 1, $command);
160        }
161    }
162    $result .= $content if (defined($content));
163    return $result;
164}
165
166foreach my $command (keys(%Texinfo::Common::sectioning_commands), 'node') {
167    texinfo_register_command_formatting($command, \&ffmpeg_heading_command);
168}
169
170# print the TOC where @contents is used
171if ($program_version_6_8) {
172    ff_set_from_init_file('CONTENTS_OUTPUT_LOCATION', 'inline');
173} else {
174    ff_set_from_init_file('INLINE_CONTENTS', 1);
175}
176
177# make chapters <h2>
178ff_set_from_init_file('CHAPTER_HEADER_LEVEL', 2);
179
180# Do not add <hr>
181ff_set_from_init_file('DEFAULT_RULE', '');
182ff_set_from_init_file('BIG_RULE', '');
183
184# Customized file beginning
185sub ffmpeg_begin_file($$$)
186{
187    my $self = shift;
188    my $filename = shift;
189    my $element = shift;
190
191    my $command;
192    if ($element and $self->get_conf('SPLIT')) {
193        $command = $self->element_command($element);
194    }
195
196    my ($title, $description, $encoding, $date, $css_lines,
197        $doctype, $bodytext, $copying_comment, $after_body_open,
198        $extra_head, $program_and_version, $program_homepage,
199        $program, $generator);
200    if ($program_version_num >= 7.000000) {
201        ($title, $description, $encoding, $date, $css_lines,
202         $doctype, $bodytext, $copying_comment, $after_body_open,
203         $extra_head, $program_and_version, $program_homepage,
204         $program, $generator) = $self->_file_header_information($command);
205    } else {
206        ($title, $description, $encoding, $date, $css_lines,
207         $doctype, $bodytext, $copying_comment, $after_body_open,
208         $extra_head, $program_and_version, $program_homepage,
209         $program, $generator) = $self->_file_header_informations($command);
210    }
211
212    my $links = $self->_get_links ($filename, $element);
213
214    my $head1 = $ENV{"FFMPEG_HEADER1"} || <<EOT;
215<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
216<html>
217<!-- Created by $program_and_version, $program_homepage -->
218  <head>
219    <meta charset="utf-8">
220    <title>
221EOT
222    my $head_title = <<EOT;
223      $title
224EOT
225
226    my $head2 = $ENV{"FFMPEG_HEADER2"} || <<EOT;
227    </title>
228    <meta name="viewport" content="width=device-width,initial-scale=1.0">
229    <link rel="stylesheet" type="text/css" href="bootstrap.min.css">
230    <link rel="stylesheet" type="text/css" href="style.min.css">
231  </head>
232  <body>
233    <div class="container">
234      <h1>
235EOT
236
237    my $head3 = $ENV{"FFMPEG_HEADER3"} || <<EOT;
238      </h1>
239EOT
240
241    return $head1 . $head_title . $head2 . $head_title . $head3;
242}
243if ($program_version_6_8) {
244    texinfo_register_formatting_function('format_begin_file', \&ffmpeg_begin_file);
245} else {
246    texinfo_register_formatting_function('begin_file', \&ffmpeg_begin_file);
247}
248
249sub ffmpeg_program_string($)
250{
251  my $self = shift;
252  if (defined($self->get_conf('PROGRAM'))
253      and $self->get_conf('PROGRAM') ne ''
254      and defined($self->get_conf('PACKAGE_URL'))) {
255    return $self->convert_tree(
256      $self->gdt('This document was generated using @uref{{program_homepage}, @emph{{program}}}.',
257         { 'program_homepage' => $self->get_conf('PACKAGE_URL'),
258           'program' => $self->get_conf('PROGRAM') }));
259  } else {
260    return $self->convert_tree(
261      $self->gdt('This document was generated automatically.'));
262  }
263}
264if ($program_version_6_8) {
265    texinfo_register_formatting_function('format_program_string', \&ffmpeg_program_string);
266} else {
267    texinfo_register_formatting_function('program_string', \&ffmpeg_program_string);
268}
269
270# Customized file ending
271sub ffmpeg_end_file($)
272{
273    my $self = shift;
274    my $program_string = &{get_formatting_function($self,'format_program_string')}($self);
275    my $program_text = <<EOT;
276      <p style="font-size: small;">
277        $program_string
278      </p>
279EOT
280    my $footer = $ENV{FFMPEG_FOOTER} || <<EOT;
281    </div>
282  </body>
283</html>
284EOT
285    return $program_text . $footer;
286}
287if ($program_version_6_8) {
288    texinfo_register_formatting_function('format_end_file', \&ffmpeg_end_file);
289} else {
290    texinfo_register_formatting_function('end_file', \&ffmpeg_end_file);
291}
292
293# Dummy title command
294# Ignore title. Title is handled through ffmpeg_begin_file().
295ff_set_from_init_file('USE_TITLEPAGE_FOR_TITLE', 1);
296sub ffmpeg_title($$$$)
297{
298    return '';
299}
300
301texinfo_register_command_formatting('titlefont',
302                                    \&ffmpeg_title);
303
304# Customized float command. Part of code borrowed from GNU Texinfo.
305sub ffmpeg_float($$$$$)
306{
307    my $self = shift;
308    my $cmdname = shift;
309    my $command = shift;
310    my $args = shift;
311    my $content = shift;
312
313    my ($caption, $prepended);
314    if ($program_version_num >= 7.000000) {
315        ($caption, $prepended) = Texinfo::Convert::Converter::float_name_caption($self,
316                                                                                 $command);
317    } else {
318        ($caption, $prepended) = Texinfo::Common::float_name_caption($self,
319                                                                     $command);
320    }
321    my $caption_text = '';
322    my $prepended_text;
323    my $prepended_save = '';
324
325    if ($self->in_string()) {
326        if ($prepended) {
327            $prepended_text = $self->convert_tree_new_formatting_context(
328                $prepended, 'float prepended');
329        } else {
330            $prepended_text = '';
331        }
332        if ($caption) {
333            $caption_text = $self->convert_tree_new_formatting_context(
334                {'contents' => $caption->{'args'}->[0]->{'contents'}},
335                'float caption');
336        }
337        return $prepended.$content.$caption_text;
338    }
339
340    my $id = $self->command_id($command);
341    my $label;
342    if (defined($id) and $id ne '') {
343        $label = "<a name=\"$id\"></a>";
344    } else {
345        $label = '';
346    }
347
348    if ($prepended) {
349        if ($caption) {
350            # prepend the prepended tree to the first paragraph
351            my @caption_original_contents = @{$caption->{'args'}->[0]->{'contents'}};
352            my @caption_contents;
353            my $new_paragraph;
354            while (@caption_original_contents) {
355                my $content = shift @caption_original_contents;
356                if ($content->{'type'} and $content->{'type'} eq 'paragraph') {
357                    %{$new_paragraph} = %{$content};
358                    $new_paragraph->{'contents'} = [@{$content->{'contents'}}];
359                    unshift (@{$new_paragraph->{'contents'}}, {'cmdname' => 'strong',
360                             'args' => [{'type' => 'brace_command_arg',
361                                                    'contents' => [$prepended]}]});
362                    push @caption_contents, $new_paragraph;
363                    last;
364                } else {
365                    push @caption_contents, $content;
366                }
367            }
368            push @caption_contents, @caption_original_contents;
369            if ($new_paragraph) {
370                $caption_text = $self->convert_tree_new_formatting_context(
371                 {'contents' => \@caption_contents}, 'float caption');
372                $prepended_text = '';
373            }
374        }
375        if ($caption_text eq '') {
376            $prepended_text = $self->convert_tree_new_formatting_context(
377                $prepended, 'float prepended');
378            if ($prepended_text ne '') {
379                $prepended_save = $prepended_text;
380                $prepended_text = '<p><strong>'.$prepended_text.'</strong></p>';
381            }
382        }
383    } else {
384        $prepended_text = '';
385    }
386
387    if ($caption and $caption_text eq '') {
388        $caption_text = $self->convert_tree_new_formatting_context(
389            $caption->{'args'}->[0], 'float caption');
390    }
391    if ($prepended_text.$caption_text ne '') {
392        if ($program_version_num >= 7.000000) {
393            $prepended_text = $self->html_attribute_class('div',['float-caption']). '>'
394                    . $prepended_text;
395        } else {
396            $prepended_text = $self->_attribute_class('div','float-caption'). '>'
397                    . $prepended_text;
398        }
399        $caption_text .= '</div>';
400    }
401    my $html_class = '';
402    if ($prepended_save =~ /NOTE/) {
403        $html_class = 'info';
404        $prepended_text = '';
405        $caption_text   = '';
406    } elsif ($prepended_save =~ /IMPORTANT/) {
407        $html_class = 'warning';
408        $prepended_text = '';
409        $caption_text   = '';
410    }
411    if ($program_version_num >= 7.000000) {
412        return $self->html_attribute_class('div', [$html_class]). '>' . "\n" .
413            $prepended_text . $caption_text . $content . '</div>';
414    } else {
415        return $self->_attribute_class('div', $html_class). '>' . "\n" .
416            $prepended_text . $caption_text . $content . '</div>';
417    }
418}
419
420texinfo_register_command_formatting('float',
421                                    \&ffmpeg_float);
422
4231;
424