root/applications/bdmtoolbox/doc/from_bdm/filter_html.pl @ 1417

Revision 1065, 8.5 kB (checked in by miro, 14 years ago)

removed top navigation

  • Property svn:executable set to *
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5use utf8;
6#use bigint;
7use List::MoreUtils qw(uniq);
8use HTML::TreeBuilder;
9use Data::Dumper;
10use Getopt::Long;
11use UNIVERSAL 'isa';
12
13my $class    = 'bdm::egiw';
14my @to_keep  = ('from_setting', 'to_setting');
15my $output_dir = '../html/bdm_doc';
16my $input_dir = '../../../../library/doc/html/';
17
18GetOptions(
19    'class=s'      => \$class,
20    'to-keep=s'    => \@to_keep,
21    'output-dir=s' => \$output_dir,
22    'input-dir=s' => \$input_dir,
23) or die('Wrong options format');
24
25my $filename = $class;
26$filename =~ s/bdm::/classbdm_1_1/;
27$filename =~ s/$/.html/;
28my $out_filename = $output_dir . '/' . $filename;
29open (my $OUT, ">$out_filename") 
30    or die "cannot open $filename: $!";
31$filename = $input_dir . '/' . $filename;
32
33print STDERR "Processing $filename\n";
34
35my $html = HTML::TreeBuilder->new();
36$html->store_comments(1);
37$html->parse_file($filename);
38
39my $body        = $html->content_array_ref()->[1];
40my $i = 0;
41my $div_content;
42while ($div_content = $body->content_array_ref()->[$i++]) {
43    last if (defined $div_content->attr('class')) 
44         && ($div_content->attr('class') eq 'contents');
45}
46$i = 0;
47my $table;
48
49FIND_TABLE:
50while ($table = $div_content->content_array_ref()->[$i++]) {
51    if ( isa($table, "HTML::Element") ) {
52        last if $table->tag() eq 'table';
53        my $container = $table;
54        my $j = 0;
55        while ($table = $container->content_array_ref()->[$j++]) {
56            last FIND_TABLE if isa($table, "HTML::Element") && ($table->tag() eq 'table');
57        }
58    }
59}
60
61#;;print STDERR $table;
62#;;print_content($table, 0, 5);
63#;;print_content($div_content, 0, 5);
64
65# generate mappings between member names and references
66# find hrefs contained in each description div
67my %ref_of;
68my %name_of;
69my %div_index_of;
70my %hrefs_of_div;
71$i = -1;
72#;;print STDERR "start with \$i = $i\n";
73while (my $node = $div_content->content_array_ref()->[++$i]) {
74    next if !ref $node;
75
76    my $comment;
77
78    if ($node->tag() eq '~comment') {
79        $comment = $node;
80    }
81    elsif($node->tag() eq 'p') {
82        next if !defined $node->content_array_ref()->[1];
83        next if !ref $node->content_array_ref()->[1];
84        $comment = $node->content_array_ref()->[1];
85        next if $comment->tag() ne '~comment';
86    }
87    else {
88        next;
89    }
90
91    my ($member, $ref)  = parse_comment($comment);
92    next if !defined $ref || !defined $member;
93
94    $name_of{$ref}      = $member;
95    $ref_of{$member}    = $ref;
96    $div_index_of{$ref} = $i+1;
97    $hrefs_of_div{$i+1} = [ find_hrefs($node->right()) ];
98}
99#;;print STDERR Data::Dumper->Dump([\%name_of], ['name_of']);
100#;;print STDERR Data::Dumper->Dump([\%div_index_of], ['div_index_of']);
101#;;print STDERR Data::Dumper->Dump([\%hrefs_of_div], ['hrefs_of_div']);
102
103# find hrefs contained in each line of summary table
104# enrich mappings between member names and references
105my %tr_index_of;
106my %hrefs_of_tr;
107$i = -1;
108while (my $tr = $table->content_array_ref()->[++$i]) {
109    next if !defined $tr->content_array_ref()->[1];
110    my $clss      = $tr->content_array_ref()->[1]->attr('class');
111    #;;print STDERR "clss: $clss\n";
112    my $anchor = $tr->content_array_ref()->[1]
113                    ->content_array_ref()->[0];
114    next if !defined $clss  ||  $clss ne 'memItemRight';
115    next if !ref $anchor    ||  $anchor->tag() ne 'a';
116
117    my ($ref) = $anchor->attr('href') =~ m/#(.*)/;
118    my $member = $class . '::' . $anchor->as_text();
119    #;;print STDERR "Member: $member\n";
120
121    $tr_index_of{$ref} = $i;
122
123    if (exists $name_of{$ref} && $name_of{$ref} ne $member) {
124        warn "inconsistency in summary table and detailed description:\n"
125             . "  $ref in summary:     $member\n" 
126             . "  $ref in description: $name_of{$ref}\n"
127             . "using the value from summary table";
128    }
129    $name_of{$ref}   = $member;
130    $ref_of{$member} = $ref;
131
132#    $hrefs_of_tr{$i} = [ find_hrefs($tr), find_hrefs($tr->right()) ];
133}
134
135#;;print STDERR Data::Dumper->Dump([\%hrefs_of_tr], ['hrefs_of_tr']);
136#;;print STDERR Data::Dumper->Dump([\%tr_index_of], ['tr_index_of']);
137#;;print STDERR Data::Dumper->Dump([\%name_of], ['name_of']);
138
139# convert given function names to refs
140my @to_keep_refs;
141for my $fn (@to_keep) {
142    push @to_keep_refs, $ref_of{$class . '::' . $fn};
143}
144#;;print STDERR Data::Dumper->Dump([\@to_keep_refs], ['to_keep_refs']);
145
146# enrich to_keep_refs with functions referenced in descriptions of to_keep
147# functions. Just one level depth, no recursion.
148my @new_to_keep_refs;
149for my $ref (@to_keep_refs) {
150#    if (exists $tr_index_of{$ref}) {
151#        push @new_to_keep_refs, @{ $hrefs_of_tr{ $tr_index_of{ $ref}} };
152#    }
153    if (exists $div_index_of{$ref}) {
154        push @new_to_keep_refs, @{ $hrefs_of_div{$div_index_of{$ref}} };
155    }
156}
157
158@to_keep_refs = uniq (@to_keep_refs, @new_to_keep_refs);
159#;;print STDERR Data::Dumper->Dump([\@to_keep_refs], ['to_keep_refs']);
160
161my @to_keep_divs = sort grep {defined} @div_index_of{@to_keep_refs};
162my @to_keep_trs  = sort grep {defined} @tr_index_of{ @to_keep_refs};
163my @to_keep_names = sort @name_of{@to_keep_refs};
164#;;print STDERR Data::Dumper->Dump([\@to_keep_divs], ['to_keep_divs']);
165#;;print STDERR Data::Dumper->Dump([\@to_keep_trs], ['to_keep_trs']);
166#;;print STDERR Data::Dumper->Dump([\@to_keep_names], ['to_keep_names']);
167
168# detach all divs which are not in to_keep_divs
169my @to_detach_divs = set_minus([values %div_index_of], \@to_keep_divs);
170#;;print STDERR Data::Dumper->Dump([\@to_detach_divs], ['to_detach_divs']);
171for my $node ( @{$div_content->content_array_ref()}[@to_detach_divs] ) {
172    $node->detach(); 
173}
174
175# detach all trs which are not in to_keep_trs
176my @to_detach_trs;
177
178$i = -1;
179while (my $tr = $table->content_array_ref()->[++$i]) {
180    my $class = $tr->content_array_ref()->[0]->attr('class');
181    next if  !defined $class   ||  $class ne 'memItemLeft';
182    next if grep {$i == $_} @to_keep_trs;
183
184    push @to_detach_trs, $i;
185
186    my $tr2 = $tr->right();
187    next if !defined $tr2;
188    my $tr2_class = $tr2->content_array_ref()->[0]->attr('class');
189    next if  !defined $tr2_class  ||  $tr2_class ne 'mdescLeft';
190
191    push @to_detach_trs, $i+1;
192}
193
194for my $node ( @{$table->content_array_ref()}[@to_detach_trs] ) {
195    $node->detach();
196}
197
198#detach whole (filtered ;-)) contents table
199$table->detach();
200
201#find and detach navigation
202$i = 0;
203my $div_navigation;
204while ($div_navigation = $body->content_array_ref()->[$i++]) {
205    last if (defined $div_navigation->attr('class')) 
206         && ($div_navigation->attr('class') eq 'navigation')
207         && (defined $div_navigation->attr('id'))
208         && ($div_navigation->attr('id') eq 'top')
209}
210$div_navigation->detach();
211
212#print the result
213print $OUT $html->as_HTML();
214
215$html->delete;
216
217#============================================================================
218
219sub set_minus { 
220    my ($original_set, $difference) = @_;
221    my @result;
222    for $i (@$original_set) {
223        next if !defined $i;
224        next if grep { $i == $_ } @$difference;
225        push @result, $i;
226    }
227    return @result;
228}
229
230# get member name and doxygen reference number out of given doxygen comment
231sub parse_comment {
232    my $comment_el = shift or return (undef, undef);
233
234    my $comment = $comment_el->as_HTML();
235    my ($member, $ref) = $comment =~ m{
236        <!-- [ ] doxytag: [ ]
237        member="(.*?)"[ ]        # *? is non-greedy
238        ref="(.*?)"
239    }xms;
240
241    return ($member, $ref);
242}
243
244
245# depth-first search
246sub dfs { 
247    my $node     = shift or return;
248    return if !ref $node; # do not process text nodes
249
250    my $function = shift or return; 
251    my $data     = shift || {};
252    my $depth    = shift || 0;
253    my $limit    = shift || 10000; #inf;
254    return if $depth > $limit;
255
256    $function->($node, $data, $depth, $limit);
257
258    for ($node->content_list()) {
259        dfs($_, $function, $data, $depth+1, $limit);
260    }
261}
262
263# find hrefs in given element which are pointing somewhere
264# into current document
265sub find_hrefs {
266    my $node  = shift;
267    my @hrefs = ();
268
269    my $fetch_href  = sub {
270        my ($node, $hrefs) = @_;
271        return if $node->tag() ne 'a' || !defined $node->attr('href');
272        my ($hashpart) = $node->attr('href') =~ m/ .*? \# (.+) /xms;
273        return if !$hashpart || !$name_of{$hashpart};
274        push @$hrefs, $hashpart;
275    };
276
277    dfs($node, $fetch_href, \@hrefs);
278    return @hrefs;
279}
280
281# print html subtree -- just for debugging
282sub print_content {
283    my ($node, $depth, $limit) = @_;
284    my $print_tag = sub {
285        my ($node, undef, $depth) = @_;
286        print STDERR " " x $depth, $node->tag(), "\n";
287        #;;print $node->as_HTML() if $node->tag() eq '~comment';
288    };
289    dfs($node, $print_tag, {}, $depth, $limit);
290}
Note: See TracBrowser for help on using the browser.