File indexing completed on 2024-04-28 11:21:09

0001 /*
0002  * mkd2html:  parse a markdown input file and generate a web page.
0003  *
0004  * usage:  mkd2html [options] filename
0005  *  or     mkd2html [options] < markdown > html
0006  *
0007  *  options
0008  *         -css css-file
0009  *         -header line-to-add-to-<HEADER>
0010  *         -footer line-to-add-before-</BODY>
0011  *
0012  * example:
0013  *
0014  *   mkd2html -css /~orc/pages.css syntax
0015  *     ( read syntax OR syntax.text, write syntax.html )
0016  */
0017 /*
0018  * Copyright (C) 2007 David L Parsons.
0019  * The redistribution terms are provided in the COPYRIGHT file that must
0020  * be distributed with this source code.
0021  */
0022 #include "config.h"
0023 
0024 #include <stdio.h>
0025 #include <stdlib.h>
0026 #include <string.h>
0027 #ifdef HAVE_BASENAME
0028 # ifdef HAVE_LIBGEN_H
0029 #  include <libgen.h>
0030 # else
0031 #  include <unistd.h>
0032 # endif
0033 #endif
0034 #include <stdarg.h>
0035 
0036 #include "mkdio.h"
0037 #include "cstring.h"
0038 #include "amalloc.h"
0039 
0040 #include "gethopt.h"
0041 
0042 char *pgm = "mkd2html";
0043 
0044 extern int notspecial(char *filename);
0045 
0046 #ifndef HAVE_BASENAME
0047 char *
0048 basename(char *path)
0049 {
0050     char *p;
0051 
0052     if ( p = strrchr(path, '/') )
0053     return 1+p;
0054     return path;
0055 }
0056 #endif
0057 
0058 void
0059 fail(char *why, ...)
0060 {
0061     va_list ptr;
0062 
0063     va_start(ptr,why);
0064     fprintf(stderr, "%s: ", pgm);
0065     vfprintf(stderr, why, ptr);
0066     fputc('\n', stderr);
0067     va_end(ptr);
0068     exit(1);
0069 }
0070 
0071 
0072 enum { GFM, ADD_CSS, ADD_HEADER, ADD_FOOTER };
0073 
0074 struct h_opt opts[] = {
0075     { GFM,           "gfm",'G', 0,       "Github style markdown" },
0076     { ADD_CSS,       "css", 0, "url",    "Additional css for this page" },
0077     { ADD_HEADER, "header", 0, "header", "Additonal headers for this page" },
0078     { ADD_FOOTER, "footer", 0, "footer", "Additional footers for this page" },
0079 };
0080 #define NROPTS (sizeof opts/sizeof opts[0])
0081 
0082 #if USE_H1TITLE
0083 extern char* mkd_h1_title(MMIOT *);
0084 #endif
0085 
0086 
0087 int
0088 main(argc, argv)
0089 char **argv;
0090 {
0091     char *h;
0092     char *source = 0, *dest = 0;
0093     MMIOT *mmiot;
0094     int i;
0095     int gfm = 0;
0096     FILE *input, *output; 
0097     STRING(char*) css, headers, footers;
0098     struct h_opt *res;
0099     struct h_context flags;
0100 
0101 
0102     CREATE(css);
0103     CREATE(headers);
0104     CREATE(footers);
0105     pgm = basename(argv[0]);
0106 
0107     hoptset(&flags, argc, argv);
0108     hopterr(&flags, 1);
0109     while ( res = gethopt(&flags, opts, NROPTS) ) {
0110     if ( res == HOPTERR ) {
0111         hoptusage(pgm, opts, NROPTS, "source [dest]");
0112         exit(1);
0113     }
0114     
0115     switch ( res->option ) {
0116     case ADD_CSS:
0117         EXPAND(css) = hoptarg(&flags);
0118         break;
0119     case ADD_HEADER:
0120         EXPAND(headers) = hoptarg(&flags);
0121         break;
0122     case ADD_FOOTER:
0123         EXPAND(footers) = hoptarg(&flags);
0124         break;
0125     case GFM:
0126         gfm = 1;
0127         break;
0128     default:
0129         fprintf(stderr, "unknown option?\n");
0130         break;
0131     }
0132     }
0133 
0134     argc -= hoptind(&flags);
0135     argv += hoptind(&flags);
0136 
0137     switch ( argc ) {
0138     char *p, *dot;
0139     case 0:
0140     input = stdin;
0141     output = stdout;
0142     break;
0143     
0144     case 1:
0145     case 2:
0146     dest   = malloc(strlen(argv[argc-1]) + 6);
0147     source = malloc(strlen(argv[0]) + 6);
0148 
0149     if ( !(source && dest) )
0150         fail("out of memory allocating name buffers");
0151 
0152     strcpy(source, argv[0]);
0153     strcpy(dest, argv[argc-1]);
0154     if (( p = strrchr(source, '/') ))
0155         p = source;
0156     else
0157         ++p;
0158 
0159     if ( (input = fopen(source, "r")) == 0 ) {
0160         strcat(source, ".text");
0161         if ( (input = fopen(source, "r")) == 0 )
0162         fail("can't open either %s or %s", argv[0], source);
0163     }
0164 
0165     if ( notspecial(dest) ) {
0166         if (( dot = strrchr(dest, '.') ))
0167         *dot = 0;
0168         strcat(dest, ".html");
0169     }
0170 
0171     if ( (output = fopen(dest, "w")) == 0 )
0172         fail("can't write to %s", dest);
0173     break;
0174 
0175     default:
0176     hoptusage(pgm, opts, NROPTS, "source [dest]");
0177     exit(1);
0178     }
0179 
0180     mmiot = gfm ? gfm_in(input, 0) : mkd_in(input, 0);
0181 
0182     if ( mmiot == 0 )
0183     fail("can't read %s", source ? source : "stdin");
0184 
0185     if ( !mkd_compile(mmiot, 0) )
0186     fail("couldn't compile input");
0187 
0188 
0189     h = mkd_doc_title(mmiot);
0190 #if USE_H1TITLE
0191     if ( ! h )
0192     h = mkd_h1_title(mmiot);
0193 #endif
0194 
0195     /* print a header */
0196 
0197     fprintf(output,
0198     "<!doctype html public \"-//W3C//DTD HTML 4.0 Transitional //EN\">\n"
0199     "<html>\n"
0200     "<head>\n"
0201     "  <meta name=\"GENERATOR\" content=\"mkd2html %s\">\n", markdown_version);
0202 
0203     fprintf(output,"  <meta http-equiv=\"Content-Type\""
0204                   " content=\"text/html; charset=utf-8\">\n");
0205 
0206     for ( i=0; i < S(css); i++ )
0207     fprintf(output, "  <link rel=\"stylesheet\"\n"
0208             "        type=\"text/css\"\n"
0209             "        href=\"%s\" />\n", T(css)[i]);
0210 
0211     fprintf(output,"  <title>");
0212     if ( h )
0213     mkd_generateline(h, strlen(h), output, 0);
0214     /* xhtml requires a <title> in the header, even if it doesn't
0215      * contain anything
0216      */
0217     fprintf(output, "</title>\n");
0218     
0219     for ( i=0; i < S(headers); i++ )
0220     fprintf(output, "  %s\n", T(headers)[i]);
0221     fprintf(output, "</head>\n"
0222             "<body>\n");
0223 
0224     /* print the compiled body */
0225 
0226     mkd_generatehtml(mmiot, output);
0227 
0228     for ( i=0; i < S(footers); i++ )
0229     fprintf(output, "%s\n", T(footers)[i]);
0230     
0231     fprintf(output, "</body>\n"
0232             "</html>\n");
0233     
0234     mkd_cleanup(mmiot);
0235     exit(0);
0236 }