#!/usr/bin/perl # rem2html # # A script to convert from the output of "remind -p" to Hyper-Text Markup # Language (HTML), the text format used in WWW documents. By default, it # outputs a stand-alone file which can be fed directly into a web browser. # The output uses nested blocks, so it will only work in a browser # which supports tables (Netscape, MSIE, etc, NOT Lynx). # # This script works well on my computer (Linux 2.0.27) under Perl 5.003 and # 5.004. It should work fine on other unices but I have no idea whether # it will run under VMS, OS/2, Windows, etc. # # [Note from David: The REMIND license prohibits you from using REMIND # under Windows.] # # Rem2html puts "normal" CAL or MSG-type reminders in a

pair, # and escapes any special HTML characters. # # If you want to put actual HTML code in the calendar (hyper-links, for # example), use the "SPECIAL HTML" type. For example: # # REM Wed SPECIAL HTML

Meeting at \ # Linux HQ

# # This file is Copyright (C) 1997-8 by Don Schwarz # and David F. Skoll # # v1.2-beta, Hal Burgiss 03/03/05 # # Changelog: # # - Fixed some mark-up mishaps for calendars with multiple months. # - Added provision for a default CSS stylesheet (remind.css), and various # related mark-up additions. # - Added a 'nomini' option for eliminating the 'small calendar' thumbnails. # - Added a 'title' option for HTML page title. # - Added a 'print' option for nicer print look. # - Added a 'months' option to control the size of the calendar. # - Added a 'dtd' option to allow control of the document DTD. # - Added some minor mark-up changes/improvements, eg xhtml compliant. # - Added capability to grok remind data from within rem2html, looking for # cgi type output, with -x option. # # A work in progress at this point. # # ######################################################################## use Getopt::Long; @months = (January,February,March,April,May,June,July,August,September,October,November,December); $def_width = '14%'; $DefaultImageDir = "%IMAGEBASE%"; $DefaultImageDir = "/images"; if ($DefaultImageDir =~ m@/$@) { chop $DefaultImageDir; } $rem2html_version = "1.2-beta"; &parse_options(); # Backgound color -- unfortunately, most Web browsers (as of 14 October 1999) # do not correctly handle transparency in PNG images, so I had to make the # moon image background white. $Options{'bgcolor'} ||= "bgcolor=\"#FFFFFF\""; # if (-t STDIN) { # print STDERR "(Rem2HTML: Input should not come from a terminal.)\n"; # $Options{'help'} = 1; # } if ($Options{'help'}) { &show_usage(); } elsif ($Options{'version'}) { print "Rem2HTML Version $rem2html_version.\n"; } else { $successes = 0; $today = &today(); $num = ($Options{'months'}) ? $Options{'months'} : 3; # get the data from remind here. $Options{'x'} && open STDIN, "$Options{'x'} |" || die "Unable to open todo file
"; if (-t STDIN) { print STDERR "(Rem2HTML: Input should not come from a terminal.)\n"; &show_usage(); } else { while(1) { last if (!parse_input()); $successes++; &output_header(); &output_data(); &output_footer(); } print STDERR "Rem2HTML: Couldn't find any calendar data.\n" if (!$successes); unless ($Options{'tableonly'}) { print < EndOfHTML } } exit(0); sub show_usage { print STDERR < --forwurl url Same as --backurl, but with the next month's small calendar --tableonly Output the results as a
block only, no , etc. --title name Set HTML --nomini Omit the small calendar thumbnails for previous/next months. --months, -m num Number of months for calendar to display. --print Minor changes to facilitate a more printable page. --border,-b size Set the border thickness of the table --cellspace,-t size Set the line thickness of the table --bgcolor,-g color Set the background color for the day entries -x cmd Run the specified remind command from within rem2html. EndOfUsage } sub escape_html { my($in) = @_; $in =~ s/\&/\&/g; $in =~ s/\</\</g; $in =~ s/\>/\>/g; return $in; } sub parse_options { %Options = (); GetOptions (\%Options, "help|h", "version", "border|b=i", "cellspace|t=i", "dtd|d=s", "backurl|bu:s", "forwurl|fu:s", "tableonly|to", "title|ti:s", "nomini|nm", "months|m:i", "prologue|p=s", "print", "append|a=s", "bgcolor|g=s", "x:s", "fs=s", "fh=s", "ft=s", "fe=s", "fd=s", "sh=i", "st=i", "se=i", "sd=i", ); $Options{'border'} = "border=" . ($Options{'border'} || 1); $Options{'cellspace'} &&= "cellspacing=$Options{'cellspace'}"; $Options{'bgcolor'} &&= "bgcolor=$Options{'bgcolor'}"; $Options{'title'} = ($Options{'title'}) ? $Options{'title'} : "Calendar"; } sub parse_input { local $where = 0; local $msg; local $type; local $day; my $title; @days = (); @shades = (); @moons = (); while (<>) { chomp($_); if (/rem2(html|ps) begin/) { } elsif (!$where) { next; } elsif ($where == 1) { # local ($month, $year); # need this later. ($month, $year, $month_length, $firstday, $mfirst) = split(" "); $caption = "$month, $year"; for $i ( 1 .. $month_length) { push(@days, ""); } } elsif ($where == 2) { @DayNames = split(" "); } elsif ($where == 3) { @prevsc = split(" "); } elsif ($where == 4) { @nextsc = split(" "); } else { return 1 if /rem2(html|ps) end/; next unless m/^(\d*).(\d*).(\d*)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s*(.*)$/; $type = $4; $msg = $8; $day = $3; if ($type eq "HTML") { $days[$day] .= "$msg "; } elsif ($type eq "MOON") { my($phase, $text); if ($msg =~ /^\s*(\d+)\s+\S+\s+\S+\s+(.*)$/) { $phase = $1; $text = $2; } elsif ($msg =~ /^\s*(\d+)/) { $phase = $1; $text = ""; } else { next; } next if ($phase > 3); if ($phase == 0) { $text = "<image src=\"$DefaultImageDir/newmoon.png\" alt=\"New Moon\"" . "width=16 height=16> <font size=\"-2\">" . escape_html($text); } elsif ($phase == 1) { $text = "<image src=\"$DefaultImageDir/firstquarter.png\" alt=\"First Quarter\"" . "width=16 height=16> <font size=\"-2\">" . escape_html($text); } elsif ($phase == 2) { $text = "<span class=\"moon\" >Full </span><image src=\"$DefaultImageDir/fullmoon.png\" alt=\"Full Moon\"" . "width=16 height=16> <font size=\"-2\">\ " . escape_html($text); } else { $text = "<image src=\"$DefaultImageDir/lastquarter.png\" alt=\"Last Quarter\"" . "width=16 height=16> <font size=\"-2\">" . escape_html($text); } $moons[$day] = $text . "</font> "; } elsif ($type eq "SHADE") { my($red, $green, $blue); if ($msg =~ /^\s*(\d+)\s+(\d+)\s+(\d+)\s*$/) { $red = $1; $green = $2; $blue = $3; } elsif ($msg =~ /^\s*(\d+)\s*$/) { $red = $1; $green = $1; $blue = $1; } else { next; } next if ($red > 255 || $green > 255 || $blue > 255); # shading done here $shades[$day] = sprintf(" class=\"shaded\" bgcolor=\"#%02X%02X%02X\"", $red, $green, $blue); } elsif ($type eq "*") { # this is the MSG from remind $title = $msg if ( $msg =~ /DETAIL:/ ); $title =~ s/.*DETAIL: //; $msg =~ s/DETAIL: .*//; $title = "title=\"$title\"" if (length($title) > 0); $msg = &escape_html($msg); # $days[$day] .= "<p class=\"msg\"><a href='#' $title>$msg</a></p>"; # $days[$day] .= "<p class=\"msg\"><span $title>$msg</span></p>"; $days[$day] .= "<span class=\"msg\" $title>$msg</span><br/>"; } } $where++; } if ($where) { return 1; } return 0; } sub output_header { local ($title, $dayheader); my $width="100%"; my $class = ($Options{'print'}) ? 'class="printable"' : ""; if ($successes eq 1) { if (!$Options{'tableonly'}) { if ($Options{'dtd'}) { open(DTD, "< $Options{'dtd'}"); print while ( <DTD> ); close(DTD); } print <<EndOfHTML; <html> <head><title>$Options{'title'} EndOfHTML } print <, updated and modified by Hal Burgiss ), and Remind (written by David F. Skoll). --> EndOfHTML } if ($Options{'prologue'}) { open(PROLOGUE, "< $Options{'prologue'}"); print while ( ); close(PROLOGUE); } $caption = &format_font($caption, $Options{'ft'}, $Options{'st'} || "+1"); print <
EndOfHTML $mfirst || &print_day_header($DayNames[0]); for($i=1; $i<7; $i++) { &print_day_header($DayNames[$i]); } $mfirst && &print_day_header($DayNames[0]); print "\n"; } sub output_footer { print "
$caption

\n\n"; if ($Options{'append'}) { open(EPILOGUE, "< $Options{'append'}"); print while ( ); close(EPILOGUE); } } } sub output_data { local ($endday, $prevday, $nextday, $week, $weekday); local ($element, $day, $msg, $fday, $id, $cell); $firstday -= $mfirst; if ($firstday < 0) { $firstday += 7; } $endday = $firstday + $month_length; $endweek = $endday + (6 - ($endday % 7)); $endday %= 7; if ( $firstday > 1 ) { $prevday = 0; $nextday = 1; } elsif ($endday ? ($endday < 5) : !$firstday) { $prevday = $endweek - 1; $nextday = $endweek; } else { $prevday = 0; $nextday = $endweek; } for $week ( 0..5 ) { print " \n"; for $weekday ( 0..6 ) { $element = ($week * 7) + ($weekday * 1); $day = $element - $firstday + 1; $cell = ($Options{'print'}) ? "print" :"cell"; $msg = $days[$day]; $id = $Options{'print'} ? "nada" : &fdate($day,$month,$year) ; $id = "today" if ("$today" eq "$id"); $id = "nada" if ( "$id" ne "today" && (length($msg) eq 0) ); $msg = $msg ? &format_font($msg, $Options{'fe'}, $Options{'se'}) : "



"; $fday = &format_font($day, $Options{'fd'}, $Options{'sd'} || -1); if ($day > 0 && $day <= $month_length) { # day numeral is here. print <
$moons[$day]$fday

$msg
EndOfHTML } elsif ($element == $prevday) { &small_calendar(@prevsc, 1, $Options{'backurl'}); } elsif ($element == $nextday) { &small_calendar(@nextsc, 2, $Options{'forwurl'}); } else { print "
"; } } print " \n"; last if $day >= $month_length && $element >= $nextday; } } sub small_calendar { local ($scname, $scn, $which, $url) = @_; local ($scstart, $l, $week, $weekday, $tday); $scname = "$scname", if $url; $scname = &format_font($scname, $Options{'fs'}, -2); if ($which == 1) { $scstart = $firstday - ($scn % 7); if ($scstart < 0) { $scstart += 7; } } else { $scstart = $firstday + ($month_length % 7); if ($scstart > 6) { $scstart -= 7; } } if ($Options{'nomini'}) { # Skip the 'small cal' stuff HB print "
"; return 1; } print < EndOfHTML $mfirst || &print_day_header(substr($DayNames[0], 0, 1), 1); for ($i=1; $i<7; $i++) { &print_day_header(substr($DayNames[$i], 0, 1), 1); } $mfirst && &print_day_header(substr($DayNames[0], 0, 1), 1); print "\n"; for $week ( 0..5 ) { print " \n"; for $weekday ( 0..6 ) { $tday = ($week * 7) + ($weekday * 1) - $scstart + 1; $tday = "", if $tday <= 0 || $tday > $scn; print " \n"; } print " \n"; last if $tday >= $scn; } print < EndOfHTML } sub format_font { local ($text, $font, $size) = @_; if (!$text) { return ""; } elsif ($font && $size) { return "$text"; } elsif ($font) { return "$text"; } elsif ($size) { return "$text"; } else { return $text; } } sub print_day_header { local ($dheader, $small) = @_; if ($small) { $dheader = &format_font($dheader, $Options{'fs'}, -2); } else { $dheader = &format_font($dheader, $Options{'fh'}, $Options{'sh'}); } print " \n"; } sub fdate($day,$month,$year) { my $fday=$day; my $fmon; if ($day < 10 ) { $fday = "0$fday"; } if ($month eq "January") { $fmon="01"; } elsif ( $month eq "February" ) { $fmon="02"; } elsif ( $month eq "March" ) { $fmon="03"; } elsif ( $month eq "April" ) { $fmon="04"; } elsif ( $month eq "May" ) { $fmon="05"; } elsif ( $month eq "June" ) { $fmon="06"; } elsif ( $month eq "July" ) { $fmon="07"; } elsif ( $month eq "August" ) { $fmon="08"; } elsif ( $month eq "September" ) { $fmon="09"; } elsif ( $month eq "October" ) { $fmon="10"; } elsif ( $month eq "November" ) { $fmon="11"; } elsif ( $month eq "December" ) { $fmon="12"; } return ("$fday$fmon$year"); } sub today() { my($s,$t,$a,$mday,$mon,$year) = localtime(time); $year+=1900; $mon++; if ( $mday < 10 ) { $mday = "0$mday"; } if ( $mon < 10 ) { $mon = "0$mon"; } return "$mday$mon$year"; }
$scname
$tday
$dheader