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 }