From 5bfc0945b06b4951e7cbae4f859c85afde9231b5 Mon Sep 17 00:00:00 2001
From: Yigit Sever
Date: Wed, 14 Aug 2024 10:39:13 +0300
Subject: bin: track rem2html

---
 .local/bin/rem2html | 790 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 790 insertions(+)
 create mode 100755 .local/bin/rem2html

diff --git a/.local/bin/rem2html b/.local/bin/rem2html
new file mode 100755
index 0000000..f298fb3
--- /dev/null
+++ b/.local/bin/rem2html
@@ -0,0 +1,790 @@
+#!/usr/bin/env perl
+# SPDX-License-Identifier: GPL-2.0-only
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+use JSON::MaybeXS;
+
+my %Options;
+
+my $rem2html_version = '2.1';
+
+my($days, $shades, $moons, $classes, $Month, $Year, $Numdays, $Firstwkday, $Mondayfirst, $weeks,
+    @Daynames, $Nextmon, $Nextlen, $Prevmon, $Prevlen);
+
+my $TIDY_PROGNAME = $0;
+$TIDY_PROGNAME =~ s|^.*/||;
+
+# rem2html -- convert the output of "remind -pp" to HTML
+
+=head1 NAME
+
+rem2html - Convert the output of "remind -pp" to HTML
+
+=head1 SYNOPSIS
+
+    remind -pp ... | rem2html [options]
+
+You can also use the old interchange format as below, but the -pp
+version is preferred.
+
+    remind -p ... | rem2html [options]
+
+=head1 OPTIONS
+
+=over 4
+
+=item --help, -h
+
+Print usage information
+
+=item --version
+
+Print version
+
+=item --backurl I<url>
+
+When producing the small calendar for the previous month, make the
+month name a link to I<url>.
+
+=item --forwurl I<url>
+
+When producing the small calendar for the next month, make the
+month name a link to I<url>.
+
+=item --imgbase I<url>
+
+When creating URLs for the stylesheet or external images, use I<url>
+as the base URL.
+
+=item --pngs
+
+Normally, rem2html uses inline "data:" URLs for the moon phase images,
+yielding a standalone HTML file.  The C<--pngs> option makes it use
+external images named firstquarter.png, fullmoon.png, lastquarter.png
+and newmoon.png, which are expected to live in C<--imgbase>.
+
+=item --stylesheet I<url.css>
+
+Use I<url.css> as the stylesheet.  If this option is used,
+I<url.css> is interpreted relative to B<imgbase> I<unless> it starts
+with a "/".
+
+=item --nostyle
+
+Produce basic HTML that does not use a CSS stylesheet.
+
+=item --tableonly
+
+Output results as a E<lt>tableE<gt> ... E<lt>/tableE<gt> sequence only
+without any E<lt>htmlE<gt> or E<lt>bodyE<gt> tags.
+
+=item --title I<title>
+
+Use I<title> as the content between E<lt>titleE<gt> and E<lt>/titleE<gt>
+tags.
+
+
+=item --prologue I<html_text>
+
+Insert I<html_text> right after the E<lt>bodyE<gt> tag.
+
+=item --epilogue I<html_text>
+
+Insert I<html_text> right before the E<lt>/bodyE<gt> tag.
+
+=back
+
+=head1 SPECIALS SUPPORTED
+
+The rem2html back-end supports the following SPECIAL reminders:
+
+=over
+
+=item HTML
+
+Add an HTML reminder to the calendar.  All HTML tags are available.
+
+=item HTMLCLASS
+
+Add a CSS class to the box representing the trigger date.  See
+"HIGHLIGHTING TODAY" for an example
+
+=item WEEK, MOON, SHARE, COLOR
+
+The standard SPECIALs supported by all back-ends
+
+=back
+
+=head1 HIGHLIGHTING TODAY
+
+Older versions of rem2html used to highlight today's date with a red outline.
+The current version does not do that by default.  If you wish to highlight
+today's date, add the following reminder to your reminders file:
+
+    REM [realtoday()] SPECIAL HTMLCLASS rem-today
+
+=head1 AUTHOR
+
+rem2html was written by Dianne Skoll with much inspiration from an
+earlier version by Don Schwarz.
+
+=head1 HOME PAGE
+
+L<https://dianne.skoll.ca/projects/remind/>
+
+=head1 SEE ALSO
+
+B<remind>, B<rem2ps>, B<rem2pdf>, B<tkremind>
+=cut
+
+sub usage
+{
+    my ($exit_status) = @_;
+    if (!defined($exit_status)) {
+	    $exit_status = 1;
+    }
+    print STDERR <<"EOM";
+$TIDY_PROGNAME: Produce an HTML calendar from the output of "remind -pp"
+
+Usage: remind -pp ... | rem2html [options]
+
+Options:
+
+--help, -h            Print usage information
+--man                 Show man page (requires "perldoc")
+--version             Print version
+--backurl url         Make the title on the previous month's small calendar
+                      entry a link to <url>
+--forwurl url         Same as --backurl, but for the next month's small calendar
+--imgbase url         Base URL of images and default stylesheet file
+--pngs                Use external .PNG images for moon phases rater than
+                      inline data: URLs
+--stylesheet url.css  URL of CSS stylesheet.  If specified, imgbase is NOT
+                      prepended to url.css
+--nostyle             Produce basic HTML that does not use a CSS stylesheet
+--tableonly           Output results as a <table> only, no <html>, <body>, etc.
+--title string        What to put in <title>...</title> tags
+--prologue html_text  Text to insert at the top of the body
+--epilogue html_text  Text to insert at the end of the body
+EOM
+    exit($exit_status);
+}
+
+sub smoosh
+{
+        my ($first, $second) = @_;
+        return $second unless defined ($first);
+        return $second if $first eq '';
+        return $second if ($second =~ m|^/|);  # Absolute path given for second
+
+        # Squash multiple slashes
+        $first =~ s|/+|/|g;
+
+        # Special case
+        return "/$second" if ($first eq '/');
+
+        # Delete trailing slash
+        $first =~ s|/$||;
+
+        return "$first/$second";
+}
+
+sub parse_options
+{
+    local $SIG{__WARN__} = sub { print STDERR "$TIDY_PROGNAME: $_[0]\n"; };
+    if (!GetOptions(\%Options, "help|h",
+		    "man",
+                    "pngs",
+		    "version",
+		    "stylesheet=s",
+		    "nostyle",
+		    "backurl=s",
+		    "forwurl=s",
+		    "title=s",
+		    "prologue=s",
+		    "epilogue=s",
+		    "imgbase=s",
+		    "tableonly")) {
+	usage(1);
+    }
+    $Options{title} ||= 'HTML Calendar';
+
+    my $stylesheet = $Options{stylesheet};
+    if ($stylesheet) {
+            $Options{stylesheet} = smoosh($Options{imgbase}, $stylesheet);
+    }
+}
+
+sub start_output
+{
+    return if ($Options{tableonly});
+
+    print("<!doctype html>\n");
+    print("<html>\n<head>\n<title>" . $Options{title} . "</title>\n");
+    print('<meta charset="utf-8">' . "\n");
+    print('<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">' . "\n");
+    if (!$Options{nostyle}) {
+	if ($Options{stylesheet}) {
+                print('<link rel="stylesheet" type="text/css" href="' .
+                      $Options{stylesheet} . '">' . "\n");
+	} else {
+                print("<style>\n");
+                print default_stylesheet();
+                print("</style>\n");
+        }
+    }
+    print("</head>\n<body>\n");
+    if ($Options{prologue}) {
+	print $Options{prologue} . "\n";
+    }
+}
+
+sub end_output
+{
+    return if ($Options{tableonly});
+    if ($Options{epilogue}) {
+	print $Options{epilogue} . "\n";
+    }
+    print("</body>\n</html>\n");
+}
+
+sub parse_input
+{
+    undef $days;
+    undef $shades;
+    undef $moons;
+    undef $classes;
+    undef $weeks;
+
+    my $found_data = 0;
+    while(<STDIN>) {
+	chomp;
+	last if /^\# rem2ps2? begin$/;
+    }
+
+    my $line;
+    # Month Year numdays firstday monday_first_flag
+    $line = <STDIN>;
+    return 0 unless $line;
+    chomp($line);
+    ($Month, $Year, $Numdays, $Firstwkday, $Mondayfirst) = split(' ', $line);
+
+    $Month =~ s/_/ /g;
+    # Day names
+    $line = <STDIN>;
+    return 0 unless $line;
+    chomp($line);
+    @Daynames = split(' ', $line);
+
+    for (my $i=0; $i<7; $i++) {
+            $Daynames[$i] =~ s/_/ /g;
+    }
+
+    # Prevmon prevlen
+    $line = <STDIN>;
+    return 0 unless $line;
+    chomp($line);
+    ($Prevmon, $Prevlen) = split(' ', $line);
+    $Prevmon =~ s/_/ /g;
+
+    # Nextmon nextlen
+    $line = <STDIN>;
+    return 0 unless $line;
+    chomp($line);
+    ($Nextmon, $Nextlen) = split(' ', $line);
+    $Nextmon =~ s/_/ /g;
+
+    $found_data = 1;
+    my $class;
+    if ($Options{nostyle}) {
+	$class = '';
+    } else {
+	$class = ' class="rem-entry"';
+    }
+    while(<STDIN>) {
+	chomp;
+	last if /^\# rem2ps2? end$/;
+	next if /^\#/;
+	my ($y, $m, $d, $special, $tag, $duration, $time, $body);
+	if (m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/) {
+		($y, $m, $d, $special, $tag, $duration, $time, $body) =
+		    ($1, $2, $3, $4, $5, $6, $7, $8);
+	} elsif (/\{/) {
+		my $obj = decode_json($_);
+		next unless ($obj->{date} =~ /^(\d+)-(\d+)-(\d+)$/);
+		$y = $1;
+		$m = $2;
+		$d = $3;
+		$special = $obj->{passthru} || '*';
+		$tag = $obj->{tags} || '*';
+		$duration = $obj->{duration} || '*';
+		$time = $obj->{time} || '*';
+		$body = $obj->{body};
+	} else {
+		next;
+	}
+	my $d1 = $d;
+	$d1 =~ s/^0+//;
+	$special = uc($special);
+	if ($special eq 'HTML') {
+	    push(@{$days->[$d]}, $body);
+	} elsif ($special eq 'HTMLCLASS') {
+	    $classes->[$d] = $body;
+	} elsif ($special eq 'WEEK') {
+		$body =~ s/^\s+//;
+		$body =~ s/\s+$//;
+		$weeks->{$d1} = $body;
+	} elsif ($special eq 'MOON') {
+		if ($body =~ /(\S+)\s+(\S+)\s+(\S+)\s+(.*)$/) {
+			my ($phase, $moonsize, $fontsize, $msg) = ($1, $2, $3, $4);
+			$moons->[$d]->{'phase'} = $phase;
+			$moons->[$d]->{'msg'} = $msg;
+		} elsif ($body =~ /(\S+)/) {
+			$moons->[$d]->{'phase'} = $1;
+			$moons->[$d]->{'msg'} = '';
+		}
+	} elsif ($special eq 'SHADE') {
+		if ($body =~ /(\d+)\s+(\d+)\s+(\d+)/) {
+			$shades->[$d] = sprintf("#%02X%02X%02X",
+						($1 % 256), ($2 % 256), ($3 % 256));
+		} elsif ($body =~ /(\d+)/) {
+			$shades->[$d] = sprintf("#%02X%02X%02X",
+						($1 % 256), ($1 % 256), ($1 % 256));
+		}
+	} elsif ($special eq 'COLOR' || $special eq 'COLOUR') {
+		if ($body =~ /(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/) {
+			my($r, $g, $b, $text) = ($1, $2, $3, $4);
+			my $color = sprintf("style=\"color: #%02X%02X%02X;\"",
+					    $r % 256, $g % 256, $b % 256);
+			push(@{$days->[$d]}, "<p$class $color>" . escape_html($text) . '</p>');
+		}
+	} elsif ($special eq '*') {
+	    push(@{$days->[$d]}, "<p$class>" . escape_html($body) . '</p>');
+	}
+    }
+    return $found_data;
+}
+
+sub small_calendar
+{
+	my($month, $monlen, $url, $first_col) = @_;
+	if ($Mondayfirst) {
+		$first_col--;
+		if ($first_col < 0) {
+			$first_col = 6;
+		}
+	}
+
+	if ($Options{nostyle}) {
+	    print "<td width=\"14%\">\n";
+	    print "<table border=\"0\">\n";
+	    print "<caption>";
+	} else {
+	    print "<td class=\"rem-small-calendar\">\n";
+	    print "<table class=\"rem-sc-table\">\n";
+	    print "<caption class=\"rem-sc-caption\">";
+	}
+	print "<a href=\"$url\">" if ($url);
+	print $month;
+	print "</a>" if ($url);
+	print "</caption>\n";
+
+	my $class;
+	if ($Options{nostyle}) {
+	    print '<tr>';
+	    $class = ' align="right"';
+	} else {
+	    print '<tr class="rem-sc-hdr-row">';
+	    $class = ' class="rem-sc-hdr"';
+	}
+	if (!$Mondayfirst) {
+		print "<th$class>" . substr($Daynames[0], 0, 1) . '</th>';
+	}
+	for (my $i=1; $i<7; $i++) {
+		print "<th$class>" . substr($Daynames[$i], 0, 1) . '</th>';
+	}
+	if ($Mondayfirst) {
+		print "<th$class>" . substr($Daynames[0], 0, 1) . '</th>';
+	}
+	print("</tr>\n");
+	my $col = 0;
+	for (; $col<$first_col; $col++) {
+		if ($col == 0) {
+			print("<tr>\n");
+		}
+		if ($Options{nostyle}) {
+		    print("<td align=\"right\" width=\"14%\">&nbsp;</td>");
+		} else {
+		    print("<td class=\"rem-sc-empty-cell\">&nbsp;</td>");
+		}
+	}
+
+	for (my $day=1; $day <= $monlen; $day++) {
+		if ($col == 0) {
+			print("<tr>\n");
+		}
+		$col++;
+		if ($Options{nostyle}) {
+		    print("<td align=\"right\" width=\"14%\">$day</td>");
+		} else {
+		    print("<td class=\"rem-sc-cell\">$day</td>");
+		}
+		if ($col == 7) {
+			print("</tr>\n");
+			$col = 0;
+		}
+	}
+	if ($col) {
+	    while ($col < 7) {
+		if ($Options{nostyle}) {
+		    print("<td align=\"right\" width=\"14%\">&nbsp;</td>");
+		} else {
+		    print("<td class=\"rem-sc-empty-cell\">&nbsp;</td>");
+		}
+		$col++;
+	    }
+	    print("</tr>\n");
+	}
+	print("</table>\n");
+	print "</td>\n";
+}
+
+sub output_calendar
+{
+    # Which column is 1st of month in?
+    my $first_col = $Firstwkday;
+    if ($Mondayfirst) {
+	$first_col--;
+	if ($first_col < 0) {
+	    $first_col = 6;
+	}
+    }
+
+    # Last column
+    my $last_col = ($first_col + $Numdays - 1) % 7;
+
+    # Figure out how many rows
+    my $number_of_rows = int(($first_col + $Numdays ) / 7 + 0.999);
+
+    # Add a row for small calendars if necessary
+    if ($first_col == 0 && $last_col == 6) {
+            $number_of_rows++;
+    }
+
+    # Start the table
+    my $class;
+    if ($Options{nostyle}) {
+	print '<table width="100%" border="1" cellspacing=\"0\"><caption>' .
+	    $Month . ' ' . $Year . '</caption>' . "\n";
+	print '<tr>';
+	$class = ' width="14%"';
+    } else {
+	print '<table class="rem-cal"><caption class="rem-cal-caption">' .
+	    $Month . ' ' . $Year . '</caption>' . "\n";
+	print '<tr class="rem-cal-hdr-row">';
+	$class = ' class="rem-cal-hdr"';
+    }
+    if (!$Mondayfirst) {
+	print "<th$class>" . $Daynames[0] . '</th>';
+    }
+    for (my $i=1; $i<7; $i++) {
+	print "<th$class>" . $Daynames[$i] . '</th>';
+    }
+    if ($Mondayfirst) {
+	print "<th$class>" . $Daynames[0] . '</th>';
+    }
+    print "</tr>\n";
+
+    # Start the calendar rows
+    my $col = 0;
+    if ($Options{nostyle}) {
+	print "<tr>\n";
+    } else {
+	print "<tr class=\"rem-cal-row rem-cal-row-$number_of_rows-rows\">\n";
+    }
+    if ($first_col > 0) {
+	small_calendar($Prevmon, $Prevlen, $Options{backurl},
+		       ($Firstwkday - $Prevlen + 35) % 7);
+	$col++;
+    }
+
+    if ($last_col == 6 && $first_col > 0) {
+	small_calendar($Nextmon, $Nextlen, $Options{forwurl},
+		       ($Firstwkday + $Numdays) % 7);
+	$col++;
+    }
+    if ($Options{nostyle}) {
+	$class = ' width="14%"';
+    } else {
+	$class = ' class="rem-empty rem-empty-$number_of_rows-rows"';
+    }
+    while ($col < $first_col) {
+	print("<td$class>&nbsp;</td>\n");
+	$col++;
+    }
+
+    for (my $day=1; $day<=$Numdays; $day++) {
+        draw_day_cell($day, $number_of_rows);
+	$col++;
+	if ($col == 7) {
+	    $col = 0;
+	    print "</tr>\n";
+	    if ($day < $Numdays) {
+		if ($Options{nostyle}) {
+		    print "<tr>\n";
+		} else {
+                    print "<tr class=\"rem-cal-row rem-cal-row-$number_of_rows-rows\">\n";
+		}
+	    }
+	}
+    }
+
+    if ($col) {
+	while ($col < 7) {
+	    if ($col == 5) {
+		if ($first_col == 0) {
+		    small_calendar($Prevmon, $Prevlen, $Options{backurl},
+				   ($Firstwkday - $Prevlen + 35) % 7);
+		} else {
+		    print("<td$class>&nbsp;</td>\n");
+		}
+	    } elsif ($col == 6) {
+		small_calendar($Nextmon, $Nextlen, $Options{forwurl},
+			       ($Firstwkday + $Numdays) % 7);
+	    } else {
+		print("<td$class>&nbsp;</td>\n");
+	    }
+	    $col++;
+	}
+	print "</tr>\n";
+    }
+
+    # Add a row for small calendars if they were not yet done!
+    if ($first_col == 0 && $last_col == 6) {
+	    if ($Options{nostyle}) {
+		    print "<tr>\n";
+	    } else {
+                    print "<tr class=\"rem-cal-row rem-cal-row-$number_of_rows-rows\">\n";
+	    }
+	    small_calendar($Prevmon, $Prevlen, $Options{backurl},
+			   ($Firstwkday - $Prevlen + 35) % 7);
+	    for (my $i=0; $i<5; $i++) {
+		print("<td$class>&nbsp;</td>\n");
+	    }
+	    small_calendar($Nextmon, $Nextlen, $Options{forwurl},
+			   ($Firstwkday + $Numdays) % 7);
+	    print("</tr>\n");
+    }
+    # End the table
+    print "</table>\n";
+}
+
+sub draw_day_cell
+{
+    my($day, $number_of_rows) = @_;
+    my $shade = $shades->[$day];
+    my $week = '';
+    if (exists($weeks->{$day})) {
+	    $week = ' ' . $weeks->{$day};
+    }
+    my $class;
+    if ($Options{nostyle}) {
+	$class = $classes->[$day] || '';
+    } else {
+	$class = $classes->[$day] || "rem-cell rem-cell-$number_of_rows-rows";
+    }
+    if ($shade) {
+	    $shade = " style=\"background: $shade;\"";
+    } else {
+	    $shade = "";
+    }
+    if ($class ne '') {
+	print "<td class=\"$class\"$shade>\n";
+    } else {
+	print "<td valign=\"top\" $shade>\n";
+    }
+    if ($moons->[$day]) {
+	    my $phase = $moons->[$day]->{'phase'};
+	    my $msg = $moons->[$day]->{'msg'};
+	    $msg ||= '';
+	    if ($msg ne '') {
+		    $msg = '&nbsp;' . escape_html($msg);
+	    }
+	    my $img;
+	    my $alt;
+	    my $title;
+	    if ($phase == 0) {
+                    if ($Options{pngs}) {
+                            $img = smoosh($Options{imgbase}, 'newmoon.png');
+                    } else {
+                            $img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAC6SURBVDiNpdNNbsIwFATgL0HKolchHKBX6yFaBOEyoPYUabvOIVKJRaCL2JX5TRNGGvnJ8ozGz89cYoElPvET+BX2yivn/1Bggw5HHMKa1h2qcPZC/JEIhvh+brIZIY6sorhMYo9hh3KGFzzfa84NZNjDt9OG/ZcH1BlaPE1IAG0+URhxzNGESKPFaHJs9Q0Ziww7HnvGeXSrJhis0jiFfjwnj3I0WRv+TKtr4hQl3lDrZ6QN9Wt654hfWfGDmBpUwDkAAAAASUVORK5CYII=';
+                    }
+		    $title = 'New Moon';
+		    $alt = 'new';
+	    } elsif ($phase == 1) {
+                    if ($Options{pngs}) {
+                            $img = smoosh($Options{imgbase}, 'firstquarter.png');
+                    } else {
+                            $img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADfSURBVDiNndM9TsNAFATgzy5yjZSAE85JBygETgENUPF3iBCitHAFQkcIhZ/Ryn9gRlrZmp2Z3ef3TBOHOMULPrDBMrhpi/4HI5xjix2+4nmJRbx/Yh7ahvkpRPVV4QDXwT3UQy46zGkAZDgK/iytefvHgCrkJsqZUH6cLnNbABSxd5Jhhf1IbkMXv8Qux7hH1Ic1xvk/jBWy6gavumvtwx7ectwZXkKh7MA95XgObeOtpI2U4zl0kGbpxgiPvwQUcXLrKFchc82f6Ur0PK49azOnmOI4TBu84zm4SV38DeIVYkrYJyNbAAAAAElFTkSuQmCC';
+                    }
+		    $title = 'First Quarter';
+		    $alt = '1st';
+	    } elsif ($phase == 2) {
+                    if ($Options{pngs}) {
+                            $img = smoosh($Options{imgbase}, 'fullmoon.png');
+                    } else {
+                            $img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADlSURBVDiNrdNBUsJAEAXQlyw4hq4hwWPqTixET6ELkZ16CcAq7oFLqXExjaYgQVNlV/Viev7/6XT/4TjGuME7PiLXUatb8N8xwB12SFjiIXIZtU/MAntEfgvQE4YtHxhiHpjXQ5H7uLhEcaLLAleBvd0Xx9Ha/BdyU+Q5OBV5OKmj7a4YBWdSyNPe4aKHAHkzqcQZNj3JgnNexqE8heyIAulffuFF3kTfIVbBVeu/xoXGGsn2TLJJ/mqkafNiINszySYZdbS90GHlvcgsWktY4TFy7ecxTdvIzahxHQLbyFXUqkPwF2ASRNYgB/PXAAAAAElFTkSuQmCC';
+                    }
+		    $alt = 'full';
+		    $title = 'Full Moon';
+	    } else {
+                    if ($Options{pngs}) {
+                            $img = smoosh($Options{imgbase}, 'lastquarter.png');
+                    } else {
+                            $img = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAGQAAABkABchkaRQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAADmSURBVDiNndMxTsNAEIXhzy5yCyQ6FAgcE7oQheQWUAAl5BIkREoZrgB0GFNkHBl7bURGsryaee/3jHeXdpxjghU+8InXyI0S+n0MMEeBEi+4jfV3vAvMQtsyL0J0j2GtViaeRRMyj8IlsgY8BSijE2Kur/hy09wHKMJrEolhwtwHKDHOsI4OLnoAXfl1jiNsOkR9keE4P8D4q4scbzg5xIxtjie709f1E7siC+9+Gx/8fxvPKtEsklcJSBdgWhcN8ByFR5z+AWgd5QpyE+OUWOJO+zJNU+Z6jHAdgHe7K73CuD5zFT9nCmRDIssCaAAAAABJRU5ErkJggg==';
+                    }
+		    $alt = 'last';
+		    $title = 'Last Quarter';
+	    }
+	    if ($Options{nostyle}) {
+		print("<div style=\"float: left\"><img border=\"0\" width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
+	    } else {
+		print("<div class=\"rem-moon\"><img width=\"16\" height=\"16\" alt=\"$alt\" title=\"$title\" src=\"$img\">$msg</div>");
+	    }
+    }
+
+    if ($Options{nostyle}) {
+	print "<div style=\"float: right\">$day$week</div>\n";
+	print "<p>&nbsp;</p>\n";
+    } else {
+	print "<div class=\"rem-daynumber\">$day$week</div>\n";
+    }
+    if ($days->[$day]) {
+	    print(join("\n", @{$days->[$day]}));
+    }
+
+    print "</td>\n";
+}
+
+sub escape_html
+{
+    my($in) = @_;
+    $in =~ s/\&/\&amp;/g;
+    $in =~ s/\</\&lt;/g;
+    $in =~ s/\>/\&gt;/g;
+    return $in;
+}
+
+parse_options();
+if ($Options{help}) {
+    usage(0);
+    exit(0);
+} elsif ($Options{man}) {
+    system("perldoc $0");
+    exit(0);
+} elsif ($Options{version}) {
+    print "rem2html version $rem2html_version.\n";
+    exit(0);
+}
+
+if (-t STDIN) { ## no critic
+    print STDERR "$TIDY_PROGNAME: Input should not come from a terminal.\n\n";
+    usage(1);
+}
+
+my $found_something = 0;
+while(1) {
+    last if (!parse_input());
+    start_output() unless $found_something;
+    $found_something = 1;
+    output_calendar();
+}
+if ($found_something) {
+    end_output();
+    exit(0);
+} else {
+    print STDERR "$TIDY_PROGNAME: Could not find any calendar data on STDIN.\n";
+    exit(1);
+}
+
+sub default_stylesheet
+{
+        return <<'EOF';
+table.rem-cal {
+  font-family: helvetica, arial, sans-serif;
+  font-size: 12pt;
+}
+
+table.rem-sc-table {
+  font-family: helvetica, arial, sans-serif;
+  font-size: 10pt;
+  width: 95%;
+  float: left;
+}
+
+caption.rem-cal-caption {
+  font-size: 14pt;
+  font-weight: bold;
+}
+
+th.rem-cal-hdr {
+  width: 14%;
+  border-style: solid;
+  border-width: 1px;
+  vertical-align: top;
+}
+td.rem-empty, td.rem-cell, td.rem-small-calendar {
+  width: 14%;
+  height: 7em;
+  border-style: solid;
+  border-width: 1px;
+  vertical-align: top;
+}
+td.rem-today {
+  width: 14%;
+  height: 7em;
+  border-style: solid;
+  border-width: 2px;
+  border-color: #EE3333;
+  vertical-align: top;
+}
+
+table.rem-cal {
+  width: 100%;
+  border-collapse: collapse;
+}
+
+div.rem-daynumber {
+  float: right;
+  text-align: right;
+  vertical-align: top;
+  font-size: 14pt;
+}
+
+p.rem-entry {
+    clear: both;
+}
+
+div.rem-moon {
+  float: left;
+  text-align: left;
+  vertical-align: top;
+}
+
+th.rem-sc-hdr {
+  text-align: right;
+}
+
+td.rem-sc-empty-cell, td.rem-sc-cell {
+  text-align: right;
+  width: 14%;
+}
+
+caption.rem-sc-caption {
+  font-size: 12pt;
+}
+EOF
+}
-- 
cgit v1.2.3-70-g09d2