235 lines
4.4 KiB
Perl
Executable File
235 lines
4.4 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# man2html (yet another one)
|
|
# written by Jan Engelhardt, 2011
|
|
#
|
|
# Most of the man2html converters on the net are either totally
|
|
# outdated or more complex than I needed.
|
|
|
|
use Text::CSV_XS;
|
|
use strict;
|
|
|
|
my $csv = Text::CSV_XS->new({eol => $/, sep_char => ' '});
|
|
my $mode = 0;
|
|
my @index;
|
|
|
|
while (<>) {
|
|
chomp($_);
|
|
my($cmd) = split(/\s/, $_);
|
|
|
|
if ($cmd eq ".\\\"" || $cmd eq ".RS" || $cmd eq ".RE") {
|
|
;
|
|
} elsif ($cmd eq ".TH") {
|
|
header($_);
|
|
} elsif ($cmd eq ".SH") {
|
|
p_end();
|
|
push(@index, [1, substr($_, 4)]);
|
|
print "<h1><a name=\"", $#index, "\"></a>",
|
|
ehtml(substr($_, 4)), "</h1>\n\n";
|
|
} elsif ($cmd eq ".SS") {
|
|
p_end();
|
|
push(@index, [2, substr($_, 4)]);
|
|
print "<h2><a name=\"", $#index, "\"></a>",
|
|
ehtml(substr($_, 4)), "</h2>\n\n";
|
|
} elsif ($cmd eq ".br") {
|
|
print "<br />\n";
|
|
} elsif ($_ eq ".B") {
|
|
p_start();
|
|
chomp(my $text = <>);
|
|
print "<b>", ehtml($text), "</b> ";
|
|
tp_adv();
|
|
} elsif ($cmd eq ".B") {
|
|
p_start();
|
|
print "<b>", ehtml(stripq(substr($_, 3))), "</b> ";
|
|
tp_adv();
|
|
} elsif ($cmd eq ".BR") {
|
|
p_start();
|
|
my(undef, $text1, $text2) = csv_split($_);
|
|
print "<b>", ehtml($text1), "</b>", ehtml($text2), " ";
|
|
tp_adv();
|
|
} elsif ($cmd eq ".BI") {
|
|
p_start();
|
|
my(undef, $text1, $text2) = csv_split($_);
|
|
print "<b>", ehtml($text1), "</b><i>", ehtml($text2), "</i> ";
|
|
tp_adv();
|
|
} elsif ($cmd eq ".IR") {
|
|
p_start();
|
|
my(undef, $text1, $text2) = csv_split($_);
|
|
print "<i>", ehtml($text1), "</i>", ehtml($text2), " ";
|
|
tp_adv();
|
|
} elsif ($_ eq ".I") {
|
|
p_start();
|
|
chomp(my $text = <>);
|
|
print "<i>", ehtml($text), "</i> ";
|
|
tp_adv();
|
|
} elsif ($cmd eq ".I") {
|
|
p_start();
|
|
print "<i>", ehtml(stripq(substr($_, 3))), "</i> ";
|
|
tp_adv();
|
|
} elsif ($cmd eq ".P" || $cmd eq ".PP") {
|
|
p_end();
|
|
pp_start();
|
|
} elsif ($cmd eq ".TP") {
|
|
p_end();
|
|
tp_start();
|
|
} elsif ($cmd eq ".IP") {
|
|
p_end();
|
|
ip_start();
|
|
} elsif ($cmd eq ".nf") {
|
|
print "<table><tr><td class=\"pre\">";
|
|
} elsif ($cmd eq ".fi") {
|
|
print "</td></tr></table>";
|
|
} elsif ($cmd eq ".ns") {
|
|
tp_adv();
|
|
} elsif ($_ ne "") {
|
|
p_start();
|
|
print ehtml($_), "\n";
|
|
tp_adv();
|
|
} else {
|
|
print "<br />\n<br />\n";
|
|
}
|
|
}
|
|
|
|
p_end();
|
|
|
|
if (scalar(@index) > 0) {
|
|
my $level = 0;
|
|
print "<h1>Index</h1>\n\n";
|
|
for (my $idx = 0; $idx <= $#index; ++$idx) {
|
|
my $entry = $index[$idx];
|
|
if ($level < $entry->[0]) {
|
|
print "<ol>\n";
|
|
++$level;
|
|
} elsif ($level > $entry->[0]) {
|
|
print "</ol>\n";
|
|
--$level;
|
|
}
|
|
print "<li><a href=\"#$idx\">", ehtml($entry->[1]),
|
|
"</a></li>";
|
|
}
|
|
print "</ol>\n";
|
|
}
|
|
|
|
print "</body>\n";
|
|
print "</html>\n";
|
|
|
|
sub csv_split
|
|
{
|
|
my $a = shift @_;
|
|
if ($csv->parse($a)) {
|
|
return $csv->fields();
|
|
}
|
|
}
|
|
|
|
sub p_end
|
|
{
|
|
if ($mode > 0) {
|
|
print "</p>\n\n";
|
|
$mode = 0;
|
|
}
|
|
}
|
|
|
|
sub p_start
|
|
{
|
|
if ($mode == 0) {
|
|
pp_start();
|
|
}
|
|
}
|
|
|
|
sub pp_start
|
|
{
|
|
if ($mode != 1) {
|
|
p_end();
|
|
print "<p class=\"pp j\">";
|
|
$mode = 1;
|
|
}
|
|
}
|
|
|
|
sub tp_start
|
|
{
|
|
if ($mode != 2) {
|
|
p_end();
|
|
print "<p class=\"tp1\">";
|
|
$mode = 2;
|
|
}
|
|
}
|
|
|
|
sub tp_adv
|
|
{
|
|
if ($mode == 2) {
|
|
ip_start();
|
|
}
|
|
}
|
|
|
|
sub ip_start
|
|
{
|
|
if ($mode != 3) {
|
|
p_end();
|
|
print "<p class=\"tp2 j\">";
|
|
$mode = 3;
|
|
}
|
|
}
|
|
|
|
sub ehtml
|
|
{
|
|
my $s = shift @_;
|
|
|
|
# unman
|
|
$s =~ s/\\-/-/gs;
|
|
|
|
# html
|
|
$s =~ s/&/&/gs;
|
|
$s =~ s/</</gs;
|
|
$s =~ s/>/>/gs;
|
|
if ($_[1]) {
|
|
$s =~ s/\"/"/gs;
|
|
}
|
|
|
|
# unman2
|
|
$s =~ s{\\fI(.*?)\\f[RP]}{<i>$1</i>}gs;
|
|
$s =~ s{\\fB(.*?)\\f[RP]}{<b>$1</b>}gs;
|
|
|
|
return $s;
|
|
}
|
|
|
|
sub stripq
|
|
{
|
|
my $s = shift @_;
|
|
$s =~ s/^\s+//gs;
|
|
$s =~ s/^\"(.*)\"$/$1/gs;
|
|
return $s;
|
|
}
|
|
|
|
sub header
|
|
{
|
|
my(undef, $name, $section, $date, $author, $title) =
|
|
csv_split(shift @_);
|
|
print "<html>\n";
|
|
print "<head>\n";
|
|
print "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n";
|
|
print "<title>", ehtml($name), "(", ehtml($section), ") - ", ehtml($title), "</title>\n";
|
|
print <<EOF;
|
|
<style type="text/css">
|
|
h1 { font-size: 100%; margin-top: 2em; margin-bottom: 0; }
|
|
h2 { font-size: 100%; margin-left: 4ex; margin-top: 2em; margin-bottom: 0; }
|
|
p { margin-top: 1ex; margin-bottom: 1ex; }
|
|
.j { text-align: justify; }
|
|
.pp { margin-left: 8ex; }
|
|
.tp1 { margin-left: 12ex; }
|
|
.tp2 { margin-left: 16ex; }
|
|
.pre { font-family: monospace; }
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
|
|
<table width="98%">
|
|
<tr>
|
|
EOF
|
|
print "\t\t<td>", ehtml($name), "(", ehtml($section), ")</td>\n";
|
|
print "\t\t<td align=\"center\">", ehtml($author), "</td>\n\n";
|
|
print "\t\t<td>", ehtml($name), "(", ehtml($section), ")</td>\n\n";
|
|
print "\t\t</tr>\n</table>\n\n";
|
|
}
|