#!/usr/bin/env perl
# $Id: script-csv2html.html,v 1.2 2020/08/17 17:44:19 tom Exp $
# -----------------------------------------------------------------------------
# Copyright 2014-2016,2020 by Thomas E. Dickey
#
#                         All Rights Reserved
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name(s) of the above copyright
# holders shall not be used in advertising or otherwise to promote the
# sale, use or other dealings in this Software without prior written
# authorization.
# -----------------------------------------------------------------------------
# Read a CSV (comma-separated-values) file, and generate an HTML table.

 
use warnings;
use strict;
use Getopt::Std;
use Text::CSV;
 
$| = 1;
 
our ( $opt_b$opt_d$opt_o$opt_u$opt_R$opt_W );
our %all_data;
 
sub cell_of($$) {
    my @cols = @{ $_[0] };
    my $cell = $_[1];
    return ( $cell <= $#cols ) ? $cols[$cell] : "";
}
 
sub do_file($) {
    my $filename = shift;
    my $csv = Text::CSV->new( { binary => 1 } )   # should set binary attribute.
      or die "Cannot use CSV: " . Text::CSV->error_diag();
    my @rows;
    my $wide = -1;
    open my $fh"<:encoding(utf8)"$filename or die "$filename$!";
    my $r = 0;
    while ( my $row = $csv->getline($fh) ) {
        my @cols = @$row;
        if ($opt_d) {
            for my $c ( 0 .. $#$row ) {
                printf STDERR "%d.%d:%s\n"$r$c$cols[$c];
            }
        }
        $wide = $#cols if ( $#cols > $wide );
        $rows$r++ ] = \@cols;
    }
    $csv->eof or $csv->error_diag();
    close $fh;
 
    print <<EOF;
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
  <title>generated table from $filename</title>
  <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
EOF
    my $style = 1 if ( $opt_R or $opt_W );
    printf "<style>\n"if ($style);
    if ($opt_W) {
        print <<EOF;
th.rotate {
  /* Something you can count on */
  height: 140px;
  white-space: nowrap;
}
 
th.rotate > div {
  transform: 
    /* Magic Numbers */
    translate(25px, 51px)
    /* 45 is really 360 - 45 */
    rotate(315deg);
  width: 30px;
}
th.rotate > div > span {
  border-bottom: 1px solid #ccc;
  padding: 5px 10px;
}
EOF
        if ($opt_R) {
            print <<EOF;
td {
  text-align: right;
}
td.left {
  text-align: left;
}
th.bottom {
  vertical-align: bottom;
}
EOF
        }
    }
    printf "</style>\n"if ($style);
    print <<EOF;
</head>
<body>
EOF
    printf "<table "
      . "border=\"%d\" "
      . "summary=\"%d-column table generated from $filename\">\n",
      ( $opt_b ? 1 : 0 ), $wide;
    my $mark = 0;
    for my $y ( 0 .. $#rows ) {
        my @cols = @{ $rows[$y] };
        my $row = ( $y == 0 ? "th" : "td" );
 
        # given a "." in first column, draw a line across table
        if ( $y > 0 and &cell_of$rows[$y], 0 ) eq "." ) {
            printf "<tr style=\"border-bottom:1px solid black\">"
              . "<td colspan=\"%d\">" . "</td>"
              . "</tr>\n", ( $wide + 1 );
            printf "<!-- draw a line, row %d of %d -->\n"$y + 1$#rows + 1;
            $mark = $y;
            next;
        }
 
        printf "<tr>\n";
        for my $x ( 0 .. $wide ) {
            if ( ( $x > $#cols ) or ( $cols[$xeq "" ) ) {
                my $span = 0;
                if (   $y <= ( $mark + 1 )
                    or &cell_of$rows$y - 1 ], $x ) ne "" )
                {
                    for my $z ( $y .. $#rows ) {
 
                        # a "." in first column marks a dividing line
                        last if ( &cell_of$rows[$z], 0 ) eq "." );
                        if ( &cell_of$rows[$z], $x ) eq "" ) {
                            ++$span;
                        }
                        else {
                            last;
                        }
                    }
                    $span = 1 if ( $span == 0 );
                }
                if ( $span > 1 ) {
                    printf "<%s rowspan=%d>\n"$row$span;
                    printf "</%s>\n"$row;
                }
                elsif ( $span == 1 ) {
                    printf "<%s>\n",  $row;
                    printf "</%s>\n"$row;
                }
            }
            elsif ( $opt_W and $row eq "th" ) {
                printf "<th class=\"%s\"><div><span>%s</span></div></th>\n",
                  $x == 0 ? "bottom" : "rotate"$cols[$x];
            }
            else {
                if ( $opt_R and $row eq "td" and $x == 0 ) {
                    printf "<%s class=\"left\">\n"$row;
                }
                else {
                    printf "<%s>\n"$row;
                }
                printf "%s\n",    $cols[$x];
                printf "</%s>\n"$row;
            }
        }
        printf "</tr>\n";
    }
    print <<EOF;
</table>
</body>
</html>
EOF
}
 
sub main::HELP_MESSAGE() {
    printf <<EOF;
Usage: $0 [options] [file1 [file2 [...]]]
 
Options:
  -b        make table have a border
  -d        debug (trace to STDERR)
  -o FILE   write data to output file
  -u        assume input-data is unquoted, as from compare-fkeys
  -R        right-align data except first cell on each line
  -W        format headers for wide-table
EOF
}
 
$Getopt::Std::STANDARD_HELP_VERSION = 1;
&getopts('bdo:RuW');
 
if ($opt_o) {
    open OUT, ">$opt_o" or die "Cannot open $opt_o";
    select OUT;
}
 
if ( $#ARGV >= 0 ) {
    while ( $#ARGV >= 0 ) {
        &do_fileshift @ARGV );
    }
}
else {
    die "No filename given";
}
 
1;