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

Revision 1062, 8.1 kB (checked in by miro, 14 years ago)

table with contents detached

  • 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$table->detach();
199
200#print the result
201print $OUT $html->as_HTML();
202
203$html->delete;
204
205#============================================================================
206
207sub set_minus { 
208    my ($original_set, $difference) = @_;
209    my @result;
210    for $i (@$original_set) {
211        next if !defined $i;
212        next if grep { $i == $_ } @$difference;
213        push @result, $i;
214    }
215    return @result;
216}
217
218# get member name and doxygen reference number out of given doxygen comment
219sub parse_comment {
220    my $comment_el = shift or return (undef, undef);
221
222    my $comment = $comment_el->as_HTML();
223    my ($member, $ref) = $comment =~ m{
224        <!-- [ ] doxytag: [ ]
225        member="(.*?)"[ ]        # *? is non-greedy
226        ref="(.*?)"
227    }xms;
228
229    return ($member, $ref);
230}
231
232
233# depth-first search
234sub dfs { 
235    my $node     = shift or return;
236    return if !ref $node; # do not process text nodes
237
238    my $function = shift or return; 
239    my $data     = shift || {};
240    my $depth    = shift || 0;
241    my $limit    = shift || 10000; #inf;
242    return if $depth > $limit;
243
244    $function->($node, $data, $depth, $limit);
245
246    for ($node->content_list()) {
247        dfs($_, $function, $data, $depth+1, $limit);
248    }
249}
250
251# find hrefs in given element which are pointing somewhere
252# into current document
253sub find_hrefs {
254    my $node  = shift;
255    my @hrefs = ();
256
257    my $fetch_href  = sub {
258        my ($node, $hrefs) = @_;
259        return if $node->tag() ne 'a' || !defined $node->attr('href');
260        my ($hashpart) = $node->attr('href') =~ m/ .*? \# (.+) /xms;
261        return if !$hashpart || !$name_of{$hashpart};
262        push @$hrefs, $hashpart;
263    };
264
265    dfs($node, $fetch_href, \@hrefs);
266    return @hrefs;
267}
268
269# print html subtree -- just for debugging
270sub print_content {
271    my ($node, $depth, $limit) = @_;
272    my $print_tag = sub {
273        my ($node, undef, $depth) = @_;
274        print STDERR " " x $depth, $node->tag(), "\n";
275        #;;print $node->as_HTML() if $node->tag() eq '~comment';
276    };
277    dfs($node, $print_tag, {}, $depth, $limit);
278}
Note: See TracBrowser for help on using the browser.