#!/users/fdc/bin/wermit + #!/net/u/1/f/fdc/kermit/wermit + # Replace the line just above with the full path of C-Kermit on your # computer, followed by a space and a '+' sign. # # Updates: # 2017/05/01 - 2.00: Initial release # 2017/09/05 - 3.00: Generate HTML 5 instead of HTML 4.01; # Accept keyword parameters on command line; # Always output in UTF-8; # Allow separate font for
..
. # 2017/10/02 - 3.01 Allow source file to be a symlink. # Allow suppression of character-set conversion. # 2017/10/03 - 3.02 Convert fully formed URLs in text to links # 2019/06/04 - 3.03 Also recognize FTP URLs. .version = 3.03 .verdate = 4 June 2019 set debug message off # Debugging... .\%9 := \$(DEBUG) # DEBUG=xxx on command line if def \%9 { # xxx can be ON, OFF, STDERR # If \%9 is defined but not one of the valid choices use STDERR # Example: DEBUG=1 html foo.txt if not \findex(\%9,|ON|OFF|STDERR|) .\%9 = STDERR set debug message \%9 } # Converts a plain text file to HTML. Rules for text file: # . Must be in block style, paragraphs not indented. # . Paragraphs are separated by one or more blank lines. # . Flushleft text is flowed. # . Indented text (e.g. bullet lists, blockquotes) is preserved as-is. # # Author: Frank da Cruz, the Kermit Project, Jan 2004. # Totally rewritten (as version 2.00): April 2017 # Last update: Mon May 1 14:34:50 2017 # # Requires C-Kermit 9.0.304 Dev.22 or later. # # Usage: # html inputfilename [ "title" [ outputfilename ] ] # OR: command | html "" "title" | command # OR: command | html "" "title" > outputfilename # # If a title is not specified, the first nonblank line of the text file # is used but only if it is followed by a blank line. # # Documentation: # . http://www.kermitproject.org/html.html # # Current version: # . http://www.kermitproject.org/ftp/kermit/scripts/html # # Does not handle: # . Multilevel lists # . Headings within the text # . Hanging-indent description lists # . Paragraphs indicated only by indentation of first line # . Any kind of font switching, e.g. to preserve layout of tables # or source code. # # Default configuration items (can be overriden by your ~/.htmlrc file) .destination = # Directory for HTML result .perms = 644 # Permissions for HTML result .lang = en # Language tag .color = black # Text color .bg = white # Background color .font = sans-serif # Body font .prefont = sans-serif # Font for indented sections .size = 15px # Font size .margin = 12px # Margins .max-width = # Maximum page width def USAGE { echo {\m(myname) script version \m(version)} xecho {Usage: \m(myname) inputfilename [ "title" } echo {[ outputfilename [ keyword-parameters... ]]]} echo {OR: command | \m(myname) "" "title"} echo {For details see: http://www.kermitproject.org/html.html} exit 0 } # Check version and platform define badversion exit 1 "echo C-Kermit 9.0.304 Dev.22 or later required" if LLT \v(version) 900304 badversion if EQU \v(version) 900304 { if LLT "\v(test)" "Dev.22" badversion } if not EQU "\v(system)" "UNIX" exit 1 "Sorry, this program only works on Unix" .breakchars := |34|39|42|44|46|58|59| # Chars that can terminate a URL # Makelink - call with each line of text from the source file. # If any links are found in the argument, they are converted to # HTML links, the resulting text is written out, and the return code is 1. # If no links were found, the return code is 0, indicting that the line # still needs to be written out. # define MAKELINK { # Convert a URL to an HTML link local head url tail c .s := \fcontents(\%1) # Argument string - a line of text .\%9 := \findex(http://,\m(s)) # Look for a regular URL if not \%9 .\%9 := \findex(https://,\m(s)) # or an SSL one if not \%9 .\%9 := \findex(ftp://,\m(s)) # or an FTP one if not \%9 return 0 # Indicates we did not create output .head := \s(s[1:\%9-1]) # Part of line before URL .\%7 := \findex(\32,\m(s),\%9) # Search for first space after URL if not \%7 .\%7 := \flen(\m(s))+1 # No spaces found .\%6 ::= \%7 - 1 # Position of char before space or EOL .c := \s(s[\%6.]) # The character itself .\%n := \fcode(\m(c)) # The character's numeric code .isbreak = 0 # Is it a break character? if < \%n 32 .isbreak = 1 # All controls are breaks if > \%n 126 .isbreak = 1 # All non-ASCIIs are breaks .isbreak := \findex(|\%n|,\m(breakchars)) # Specific break character if isbreak { # If it's a break character... decr \%7 2 # Back up over it } .url := \s(s[\%9_\%7]) # This is the URL .tail := \s(s[\%7+1]) # This is text that follows the URL. fwrite /string \%o {\m(head) } # Output head fwrite /string \%o {\m(url)} # Output the URL # Check if tail contains any more URLs... .\%4 ::= \findex(http://,\m(tail)) + \findex(https://,\m(tail)) if not \%4 { # If no more URLs fwrite /line \%o {\m(tail)} # output the tail } else { # otherwise makelink \m(tail) # recurse. } return 1 # This indicates we created output. } if readable ~/.htmlrc take ~/.htmlrc # Load user's default parameters if fail exit 1 "?Problem with .htmlrc" .myname := \fbasename(\%0) # Name of this script # Open input and output files .stdio = 0 # Not piping by default if defined \%1 { .\%9 := \ffileinfo(\%1,&a) # Get info about input file if not \%9 exit 1 "\%1: file not found" fopen /read \%i \fcontents(\%1) # Open it if fail exit 1 msg file \fcontents(\%1) open for input if not \findex(\&a[7],regular|link) exit 1 "\%1: Not a regular file" if ( equ "\&a[9]" "binary" ) exit 1 "\%1 is a binary file" } else { fopen /stdin \%i # "Open" the Standard Input stream if fail exit 1 # (shouldn't happen) if not background usage # Nothing waiting on stdin fopen /stdout \%o # If reading from pipe write to stdout if fail exit 1 # (shouldn't happen) .stdio = 1 # Remember we're piping msg using standard i/o } .maybehtml = 0 # Is input file already HTML? if not stdio { .filename := \fbasename(\fcontents(\%1)) # Name of input file .ext := \flop(\m(filename)) # Extension (part after the dot) .stem := \fstripx(\m(filename)) # Stem (part before the dot) if equ ".html" \m(ext) { .maybehtml = 1 } .oname := \fcontents(\%3) # Path for output file if not def oname .oname := \m(stem).html .oname := \m(destination)\m(oname) fopen /write \%o \m(oname) # Try to open the output file if fail exit 1 msg file \m(oname) open for output } while defined \%4 { # Additional command-line parameters if < \fkeywordval(\%4) 0 exit 1 "?Bad keyword-value pair" shift } undef width if def max-width .width := "max-width:\m(max-width)" if not def cset { # If character set not defined .cset = Windows-1252 # Assume the worst if equ "\&a[9]" "text:utf8" { # Now check .cset = UTF-8 # Source file is UTF-8 } } if not def noconvertcset .noconvertcset = 0 if not numeric \m(noconvertcset) exit 1 noconvertcset must be numeric msg source-file character-set: \m(cset) if noconvertcset { msg html-result character-set: \m(cset) .outcset := \m(cset) } else { msg html-result character-set: UTF-8 .outcset = utf-8 } # Major states: # 0 start # 1 in a paragraph # 2 between paragraphs .line = # Initialize operating variables .prev = .next = .state = 0 # State .\%n = 0 # Input line count .oldlen = 0 # Length of previous output line # Macro Definitions... def PUTOUT { # File output routine if > \v(argc) 2 { echo "PUTOUT: Line \%n - Too many args:" show args exit 1 } .out := \fcontents(\%1) .\%9 := \flen(\m(out)) if ( == \%9 0 && == \m(oldlen) 0 ) end 0 if equ "\m(out)" "
" fwrite /string \%o 
    else fwrite /line \%o \m(out)
    if fail exit 1 "FILE WRITE ERROR: \m(oname)"
    .oldlen := \%9
}

def GETLINE {                           # Read input line
    .prev := \m(line)                   # with lookahead and lookback
    .line := \m(next)
    undef next
    fread /line /trim /untabify \%i next
    if fail end 1
    if not noconvertcset {              # Convert line to UTF-8
        if neq "\m(cset)" "utf-8" .next := \fcvtcset(\m(next),\m(cset),utf-8)
    }
    incr \%n
#    msg \%n. [\m(line)]
}

def PUTBACK {                           # "Rewind" the current record
    .next := \m(line)                   # (works only once for any given line)
    .line := \m(prev)
    undef prev
}

def PUTLINE {                           # Write current data line
    .out := \freplace(\m(line),&,&)
    .out := \freplace(\m(out),<,<)
    .out := \freplace(\m(out),>,>)
    if lge "\v(test)" "20171007" {      # Feature added in 9.0.304 Dev.23
        .out := \freplace(\m(out),\--,—,0,1)   # "word mode" replace
        .out := \freplace(\m(out),\...,…,0,1)
    }
    makelink \m(out)                    # Convert any URLs to links
    if not \v(return) putout {\m(out)}
    if equ {\fleft(\m(out),20)} {--------------------} putout {
} if equ {\fleft(\m(out),20)} {********************} putout {
} } # Begin actions .title := \fcontents(\%2) # Check for title on command line if not def title { # No Title given while not def line { # Get first nonblank line getline if fail break } if maybehtml if \findex(DOCTYPE HTML,\m(line)) { exit 1 {?\m(name) is already html} } getline # Get line after first nonblank line if ( def prev && not def line ) { # If top line followed by blank line .title := \m(prev) # use it as the title getline # and read another line } else { # Otherwise .title = "Untitled" # use "Untitled" putback # and put this line back } } # Write prolog... putout {} # html script version 3.00: HTML5 putout {} putout {} putout {} putout {\m(title)} putout {} putout - {} putout {} putout {} putout {} putout {} if def margin putout {
} putout {

\m(title)

} putout putout {[Go to bottom]

} putout .state = 2 .blockquote = 0 if debug show args if debug show mac state first blockquote while true { # Loop for each line in file. getline # Read a line if fail break # msg Line \%n: state=\m(state) blockquote=\m(blockquote) .first = 0 # Check for an unordered list not preceded by a blank line if == \fcode(\m(line)) 32 { if not blockquote { .tmp := \fltrim(\m(line)) putout {

}
            .blockquote = 1
        }
    # A blank line becomes "

" in normal text # but must be kept as-is in a

 block to avoid gaping vertical spaces
    } else if not def line {           # This line is blank
        if ( == state 2 ) continue     # Treat consecutive blanks lines as one
        if not blockquote {            # If not in 
            putout
            putout {

} # Put a

putout .state = 2 # State becomes "between paragraphs" } else if == \fcode(\m(next)) 32 { # Keep blank line if still in

            putout                     # In 
 blank lines are like 

} continue # An indented line starts a

 block if we're not in one already
    } else if ( == \fcode(\m(line)) 32 ) { # This line is indented 
        # if ( not blockquote && ( == state 2 || == state 0 ) )
        if not blockquote {
            putout {
} 
            .blockquote = 1                
        }
    # A non-indented line terminates the active 
 block (if any)
    } else if ( > \fcode(\m(line)) 32 ) { # This line is not indented
        if blockquote {
            putout {
} putout {

} putout .state = 2 .blockquote = 0 } } .state = 1 # State becomes "in paragraph" if \%n putline # If we have a line write it out } if > \%n 0 { # Last lookahead line (if any) putline putout {

} } putout {[Go to top]} putout "


" # Write out the epilog putout {
} if not stdio putout "\fbasename(\m(oname)): \v(timestamp) ... " putout {Text to html by Kermit \m(myname) script \m(version)} # Validator (only works when result page is on the Web, obviously) putout {} putout "
" putout "
" putout " putout "" fclose \%i # And close the files fclose \%o if not stdio chmod \m(perms) \m(oname) exit ; Local Variables: ; comment-column:40 ; comment-start:"# " ; End: