http://qs321.pair.com?node_id=11117478

Lady_Aleena has asked for the wisdom of the Perl Monks concerning the following question:

I have been trying to decide for weeks whether or not I want to collapse most of my individual page-scripts (scripts that act like web pages) into their indexes and use a touch of CGI:Minimal to switch the text on a click. Below are the page-scripts for my Collections where you can see how similar they are above the __DATA__.

Link to all of the Collections; links to the modules: Base::Page (page and story), Util::StoryMagic, Util::StoryMagic::Collection.

index.pl
#!/usr/bin/perl # This is the index for Collections. use strict; use warnings FATAL => qw( all ); use CGI::Carp qw(fatalsToBrowser); use lib '../files/lib'; use Base::Page qw(page story); use Util::StoryMagic::Collection qw(collection_magic); my $magic = collection_magic; page( 'code' => sub { story(*DATA, { 'line magic' => $magic }) }); __DATA__ Welcome to Lady Aleena's B<collections>, which is lists of A<novels|hr +ef="Fiction.pl">, A<books|href="Non-fiction.pl">, A<music|href="Music +_and_comedy.pl">, A<movies|href="Movies.pl">, A<tie-ins|href="Tie-ins +.pl">, and A<programs|href="Programs.pl"> I am willing to admit I own + or use. The list of movies here is just those movies I own and shoul +d not to be confused with my more general interest in A<movies|href=" +../Movies">. Tie-ins are books and music connected to movies or telev +ision series. I also share my A<fandom|href="../Fandom"> elsewhere. Here is a key for the notations after each title with the exception of + programs.
Fiction.pl
#!/usr/bin/perl use strict; use warnings FATAL => qw( all ); use CGI::Carp qw(fatalsToBrowser); use lib '../files/lib'; use Base::Page qw(page story); use Util::StoryMagic::Collection qw(collection_magic); my $magic = collection_magic; page( 'code' => sub { story(*DATA, { 'doc magic' => $magic, 'line magi +c' => $magic }) }); __DATA__ This is my B<fiction collection> of SPAN<hardcovers|^hardcovers^>, SPA +N<trade paperbacks|^trades^>, and SPAN<mass market paperbacks|^massma +rkets^>.
Movies.pl
#!/usr/bin/perl use strict; use warnings FATAL => qw( all ); use CGI::Carp qw(fatalsToBrowser); use lib '../files/lib'; use Base::Page qw(page story); use Util::StoryMagic::Collection qw(collection_magic); my $magic = collection_magic; page( 'code' => sub { story(*DATA, { 'doc magic' => $magic, 'line magi +c' => $magic }) }); __DATA__ This is my B<movie collection> of SPAN<blu-rays|^brds^>, SPAN<DVDs|^dv +ds^>, and SPAN<VHSs|^vhss^>.
Music_and_comedy.pl
#!/usr/bin/perl use strict; use warnings FATAL => qw( all ); use CGI::Carp qw(fatalsToBrowser); use lib '../files/lib'; use Base::Page qw(page story); use Util::StoryMagic::Collection qw(collection_magic); my $magic = collection_magic; page( 'code' => sub { story(*DATA, { 'doc magic' => $magic, 'line magi +c' => $magic }) }); __DATA__ This is my B<music and comedy collection> of SPAN<LPs|^lps^>, SPAN<45s +|^ffs^>, SPAN<cassettes|^cassettes^>, and SPAN<CDs|^cds^>. If it is n +ot on a CD, I have not heard it in a long long time. SPAN<&#9785;|cla +ss="bigger">
Programs.pl
#!/usr/bin/perl use strict; use warnings FATAL => qw( all ); use CGI::Carp qw(fatalsToBrowser); use lib '../files/lib'; use Base::Page qw(page story); use Util::StoryMagic qw(program_magic); my $magic = program_magic; page( 'code' => sub { story(*DATA, { 'line magic' => $magic }) }); __DATA__ This is a list of B<programs> that I am using or have used. I can not +account for I<all> the software we have had and used over the years. +Some of it was so bad, we blanked it out of our heads. This list does + not include a full list of hardware drivers either. So much software +, so little time or in this case patience.
Tie-ins.pl
#!/usr/bin/perl use strict; use warnings FATAL => qw( all ); use CGI::Carp qw(fatalsToBrowser); use lib '../files/lib'; use Base::Page qw(page story); use Util::StoryMagic::Collection qw(collection_magic); my $magic = collection_magic; page( 'code' => sub { story(*DATA, { 'line magic' => $magic }) }); __DATA__ This is my film and television B<tie-in collection>. For books: SPAN<hardcovers|^hardcovers^>, SPAN<trade paperbacks|^trade +s^>, and SPAN<mass market paperbacks|^massmarkets^>. For music: SPAN<CDs|^cds^>, SPAN<cassettes|^cassettes^>, SPAN<45s|^ffs +^>, and SPAN<LPs|^lps^>.

With the above being so similar, I can collapse them into one umbrella script that is below.

#!/usr/bin/perl # This is the index for Collections. use strict; use warnings FATAL => qw( all ); use CGI::Carp qw(fatalsToBrowser); use CGI::Minimal; use HTML::Entities qw(encode_entities); use lib '../files/lib'; use Base::Page qw(page story); use Util::Data qw(file_directory file_list); use Util::StoryMagic qw(program_magic); use Util::StoryMagic::Collection qw(collection_magic); my $cgi = CGI::Minimal->new; my $collection = $cgi->param('collection') ? encode_entities($cg +i->param('collection'),'<>"') : undef; my $magic = $collection && $collection eq 'Program' ? progr +am_magic : collection_magic; my $collections_dir = file_directory('Collections'); my @collections_list = file_list($collections_dir); my @collections = map { $_ =~ s/\.txt//; $_ =~ s/_/ /g; $_ } grep {/^\p{uppercase}/} @collections_list; my $heading = q(Lady Aleena's ); $heading .= $collection && grep( $collection =~ /$_/, @coll +ections ) ? lc "$collection collection" : 'collections'; my $collection_file = $collection ? "$collections_dir/$collection.txt +" : "$collections_dir/index.txt"; $collection_file =~ s/ /_/g; open(my $collection_fh, '<', $collection_file) || die $!; page( 'heading' => $heading, 'code' => sub { story($collection_fh, { 'doc magic' => $magic, 'line magic' => $magic }); } );

(file_directory and file_list are in Util::Data in the above and in the sub below.)

The above script works as expected, but I would not be posting here if there were not a problem. The problem is my site's menu is built by recursing through the directory structure of my site and uses the files and directories it finds to make the menu. If I were to collapse the 155 page-scripts into the 25 index scripts, I would lose the links to the topics those separate page-scripts now have. I did something very close to this a while ago, and I have not liked that the directory does not have entries for each topic. That directory may not get any traffic because it appears that there is nothing much there.

Side note, I did not realize I had so many page-scripts.

I use my base_menu sub (below) to make the menu for my site and would like to know how you would populate the directories that have only one file in them. With base_menu, all I have to do is add a page-script and refresh, and the menu is updated. Without those page-scripts, the menu will be almost empty.

sub base_menu { my %opt = @_; my $directory = $opt{'directory'}; my $curr_cwd = cwd; my @contents = file_list($directory); @contents = grep {/^\p{uppercase}/} @contents if (!$opt{'full'} || $ +opt{'full'} !~ /^[yt1]/); # Thank you [tye]! # Thank you [davido]! my $sub = $directory =~ /(Other_poets|Player_characters|Spellbooks)$ +/ ? \&name_sort : \&article_sort; @contents = sort { $sub->($a, $b, { 'misc' => $opt{'misc'} }) } @con +tents; my (@files, @directories); for my $content (@contents) { my $long_content = "$directory/$content"; my $link = File::Spec->abs2rel($long_content); my $text = $content !~ /^\./ ? textify($content) : $content; if (-f $long_content) { my $active = realpath($0) eq $long_content ? 'active' : 'inactiv +e'; my $color = $opt{'color'} == 1 ? link_color($content,1) : undef +; my $inlist = $active eq 'active' && $opt{'file menu'} ? ['u', $o +pt{'file menu'}, { 'class' => 'sub_menu' }] : undef; $active .= $active eq 'active' && $opt{'file menu'} ? ' open' +: ''; if (-M $long_content < 3) { $active .= ' updated'; } push @files, [anchor($text, { 'href' => $link, 'title' => $text, + 'style' => $color }), { 'class' => $active, 'inlist' => $inlist } ]; } if (-d $long_content) { my $active = $curr_cwd =~ /$long_content/ ? 'open active' : 'clo +sed inactive'; my $file_list; my $index = "$long_content/index.pl"; if (-e $index) { $link .= "/index.pl"; my $color = $opt{'color'} == 1 ? link_color($link,1) : undef; $text = anchor($text, { 'href' => $link, 'title' => $text, 'st +yle' => $color }); $file_list = "$curr_cwd/$0" =~ /$index/ && $active =~ / active +$/ && $opt{'file menu'} ? $opt{'file menu'} : undef; } my $next_list = base_menu( 'directory' => $long_content, 'color' => $opt{'color'}, 'full' => $opt{'full'}, 'misc' => $opt{'misc'}, 'file menu' => $opt{'file menu'} ); push @$next_list, @$file_list if $file_list; my $inlist = $next_list ? ['u', $next_list] : undef; $active =~ s/^(?:open|closed) // if !$inlist; push @directories, [$text, { 'class' => $active, 'inlist' => $in +list}]; } } my @file_lines = (@files, @directories); return @file_lines > 0 ? \@file_lines : undef; }

(base_menu is in Util::Menu, name_sort and article_sort are in Util::Sort, textify is in Util::Convert.)

So, why did I post this? I would like to know if this way appears better? I also need ideas on how to collapse these page-scripts into their indexes without losing the automatic addition to the menu that I have now. There are a few scripts that do not use story, and those are the hardest to figure out how to add to the menu since they will not have a text file to go with it.

Thank you for reading this latest bit of my craziness.

There is an update below.

My OS is Debian 10 (Buster); my perl versions are 5.28.1 local and 5.8.8 on web host.

Version control is a non-issue, I do not use it.

No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
Lady Aleena