diff --git a/latex.c b/latex.c index 16e7d0c..cddb8ac 100644 --- a/latex.c +++ b/latex.c @@ -94,7 +94,10 @@ void print_latex_node(GString *out, node *n, scratch_pad *scratch) { print_latex_node_tree(out,n->children,scratch); break; case STR: - print_latex_string(out,n->str, scratch); + if (scratch->extensions & EXT_LATEX_PASSTHRU) + print_latex_unescaped_string(out, n->str, scratch); + else + print_latex_string(out,n->str, scratch); break; case ABBREVIATION: /* We combine the short and full names, since stripping non-ascii characters may result @@ -1121,6 +1124,16 @@ void print_latex_localized_typography(GString *out, int character, scratch_pad * } } +/* print_latex_unescaped_string - print string, not escaping for LaTeX */ +void print_latex_unescaped_string(GString *out, char *str, scratch_pad *scratch) { + if (str == NULL) + return; + while (*str != '\0') { + g_string_append_c(out, *str); + str++; + } +} + /* print_latex_string - print string, escaping for LaTeX */ void print_latex_string(GString *out, char *str, scratch_pad *scratch) { char *tmp; diff --git a/latex.h b/latex.h index 1f0f34b..e31b535 100644 --- a/latex.h +++ b/latex.h @@ -8,6 +8,7 @@ void print_latex_node_tree(GString *out, node *list, scratch_pad *scratch); void print_latex_node(GString *out, node *n, scratch_pad *scratch); void print_latex_localized_typography(GString *out, int character, scratch_pad *scratch); +void print_latex_unescaped_string(GString *out, char *str, scratch_pad *scratch); void print_latex_string(GString *out, char *str, scratch_pad *scratch); void print_latex_url(GString *out, char *str, scratch_pad *scratch); void print_latex_endnotes(GString *out, scratch_pad *scratch); diff --git a/libMultiMarkdown.h b/libMultiMarkdown.h index 5f1990b..552397f 100644 --- a/libMultiMarkdown.h +++ b/libMultiMarkdown.h @@ -48,6 +48,7 @@ enum parser_extensions { EXT_ESCAPED_LINE_BREAKS = 1 << 17, /* Escaped line break */ EXT_NO_STRONG = 1 << 18, /* Don't allow nested 's */ EXT_NO_EMPH = 1 << 19, /* Don't allow nested 's */ + EXT_LATEX_PASSTHRU = 1 << 20, /* LaTeX passthru */ EXT_FAKE = 1 << 31, /* 31 is highest number allowed */ }; diff --git a/multimarkdown.c b/multimarkdown.c index 9b7dfda..6181f3a 100644 --- a/multimarkdown.c +++ b/multimarkdown.c @@ -2,17 +2,17 @@ parser.leg -> parser.c -- Parse (Multi)Markdown plain text for conversion into other formats - + (c) 2013-2015 Fletcher T. Penney (http://fletcherpenney.net/). Derived from peg-multimarkdown, which was forked from peg-markdown, - which is (c) 2008 John MacFarlane (jgm at berkeley dot edu), and + which is (c) 2008 John MacFarlane (jgm at berkeley dot edu), and licensed under GNU GPL or MIT. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License or the MIT license. See LICENSE for details. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -44,10 +44,11 @@ int main(int argc, char **argv) static int no_obfuscate_flag = 0; static int process_html_flag = 0; static int random_footnotes_flag = 0; + static int latex_passthru_flag = 0; bool list_meta_keys = 0; bool list_transclude_manifest = 0; char *target_meta_key = FALSE; - + static struct option long_options[] = { {"batch", no_argument, &batch_flag, 1}, /* process each file separately */ {"to", required_argument, 0, 't'}, /* which output format to use */ @@ -73,32 +74,33 @@ int main(int argc, char **argv) {"version", no_argument, 0, 'v'}, /* display version information */ {"help", no_argument, 0, 'h'}, /* display usage information */ {"manifest", no_argument, 0, 'x'}, /* List all transcluded files */ + {"passthru", no_argument, 0, 'p'}, /* Enable LaTeX passthru */ {NULL, 0, NULL, 0} }; - + GString *inputbuf; GString *manifest; FILE *input; FILE *output; int curchar; GString *filename = NULL; - + char *out; - + /* set up my data for the parser */ int output_format = HTML_FORMAT; /* Default output format unless specified otherwise */ unsigned long extensions = 0; extensions = extensions | EXT_SMART | EXT_NOTES | EXT_OBFUSCATE; - + /* process options */ while (1) { int option_index = 0; - c = getopt_long (argc, argv, "vhco:bfst:me:arx", long_options, &option_index); - + c = getopt_long (argc, argv, "vhco:bfst:me:arxp", long_options, &option_index); + if (c == -1) break; - + switch (c) { case 0: /* handle long_options */ /* printf ("option %s", long_options[option_index].name); @@ -106,20 +108,20 @@ int main(int argc, char **argv) printf (" with arg %s", optarg); printf("\n"); */ break; - + case 'b': /* batch */ batch_flag = 1; break; - + case 'c': /* compatibility */ compatibility_flag = 1; break; - + case 'o': /* output filename */ if (optarg) filename = g_string_new(optarg); break; - + case 'v': /* show version */ printf("\nMultiMarkdown version %s\n%s\n",MMD_VERSION, MMD_COPYRIGHT); return(EXIT_SUCCESS); @@ -151,12 +153,13 @@ int main(int argc, char **argv) " --labels, --nolabels Disable id attributes for headers\n" " --mask, --nomask Mask email addresses in HTML\n" " --escaped-line-breaks Enable escaped line breaks\n" + " -p, --passthru Enable latex passthru\n" "\nAvailable FORMATs: html(default), latex, beamer, memoir, odf, opml, lyx, mmd\n\n" "NOTE: The lyx output format was created by Charles R. Cowan, and \n\tis provided as is.\n\n\n" ); return(EXIT_SUCCESS); - + case 't': /* output format */ if (strcmp(optarg, "text") == 0) output_format = TEXT_FORMAT; @@ -184,15 +187,15 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } break; - + case 'f': /* full doc */ extensions = extensions | EXT_COMPLETE; break; - + case 's': /* snippet only */ extensions = extensions | EXT_SNIPPET; break; - + case 'm': /* list metadata */ list_meta_keys = 1; break; @@ -200,28 +203,32 @@ int main(int argc, char **argv) case 'e': /* extract metadata */ target_meta_key = strdup(optarg); break; - + case '?': /* long handles */ break; - + case 'a': /* Accept CriticMarkup changes */ extensions = extensions | EXT_CRITIC_ACCEPT; break; - + case 'r': /* Reject CriticMarkup changes */ extensions = extensions | EXT_CRITIC_REJECT; break; - + case 'x': /* List transcluded files */ list_transclude_manifest = 1; break; + case 'p': /* enable LaTeX passthru */ + latex_passthru_flag = 1; + break; + default: fprintf(stderr,"Error parsing options.\n"); abort(); } - } - + } + /* Compatibility mode emulates the behavior of Markdown.pl */ if (compatibility_flag) { extensions = 0x000000; @@ -231,13 +238,13 @@ int main(int argc, char **argv) /* apply extensions from long options*/ if (complete_flag) extensions = extensions | EXT_COMPLETE; - + if (snippet_flag) extensions = extensions | EXT_SNIPPET; - + if (notes_flag) extensions = extensions | EXT_NOTES; - + if (no_notes_flag) extensions &= ~EXT_NOTES; @@ -252,7 +259,7 @@ int main(int argc, char **argv) if (no_label_flag) extensions = extensions | EXT_NO_LABELS; - + if (obfuscate_flag) extensions = extensions | EXT_OBFUSCATE; @@ -261,7 +268,7 @@ int main(int argc, char **argv) if (process_html_flag) extensions = extensions | EXT_PROCESS_HTML; - + if (random_footnotes_flag) extensions = extensions | EXT_RANDOM_FOOT; @@ -271,21 +278,24 @@ int main(int argc, char **argv) /* Enable HEADINGSECTION for certain formats */ if ((output_format == OPML_FORMAT) || (output_format == BEAMER_FORMAT) || (output_format == LYX_FORMAT)) extensions = extensions | EXT_HEADINGSECTION; - + + if ((output_format == LATEX_FORMAT) && latex_passthru_flag) + extensions = extensions | EXT_LATEX_PASSTHRU; + /* fix numbering to account for options */ argc -= optind; argv += optind; - + /* We expect argc and argv to still point just one below the start of remaining args */ argc++; argv--; - + /* any filenames */ numargs = argc -1; if (batch_flag && (numargs != 0)) { /* we have multiple file names -- handle individually */ - + for (i = 0; i < numargs; i++) { inputbuf = g_string_new(""); manifest = g_string_new(""); @@ -299,11 +309,11 @@ int main(int argc, char **argv) g_string_free(filename, true); exit(EXIT_FAILURE); } - + while ((curchar = fgetc(input)) != EOF) g_string_append_c(inputbuf, curchar); fclose(input); - + /* list metadata keys */ if (list_meta_keys) { out = extract_metadata_keys(inputbuf->str, extensions); @@ -315,7 +325,7 @@ int main(int argc, char **argv) return(EXIT_SUCCESS); } } - + /* extract metadata */ if (target_meta_key) { out = extract_metadata_value(inputbuf->str, extensions, target_meta_key); @@ -326,7 +336,7 @@ int main(int argc, char **argv) free(target_meta_key); return(EXIT_SUCCESS); } - + if (!(extensions & EXT_COMPATIBILITY)) { temp = strdup(argv[i+1]); folder = dirname(temp); @@ -355,7 +365,7 @@ int main(int argc, char **argv) out = markdown_to_string(inputbuf->str, extensions, output_format); g_string_free(inputbuf, true); } - + /* set up for output */ temp = argv[i+1]; /* get current filename */ if (strrchr(temp,'.') != NULL) { @@ -365,9 +375,9 @@ int main(int argc, char **argv) temp[count] = '\0'; } } - + filename = g_string_new(temp); - + if (output_format == TEXT_FORMAT) { g_string_append(filename,".txt"); } else if (output_format == HTML_FORMAT) { @@ -392,16 +402,16 @@ int main(int argc, char **argv) /* default extension -- in this case we only have 1 */ g_string_append(filename,".txt"); } - + if (!(output = fopen(filename->str, "w"))) { perror(filename->str); } else { fprintf(output, "%s\n",out); fclose(output); } - + g_string_free(filename,true); - + if (out != NULL) free(out); } @@ -434,13 +444,13 @@ int main(int argc, char **argv) free(temp); exit(EXIT_FAILURE); } - + while ((curchar = fgetc(input)) != EOF) g_string_append_c(inputbuf, curchar); fclose(input); } } - + if (!(extensions & EXT_COMPATIBILITY)) { prepend_mmd_header(inputbuf); append_mmd_footer(inputbuf); @@ -482,7 +492,7 @@ int main(int argc, char **argv) g_string_free(manifest, true); return(EXIT_SUCCESS); } else { - g_string_free(manifest, true); + g_string_free(manifest, true); } if (output_format == ORIGINAL_FORMAT) { @@ -493,7 +503,7 @@ int main(int argc, char **argv) out = markdown_to_string(inputbuf->str, extensions, output_format); g_string_free(inputbuf, true); } - + /* did we specify an output filename; "-" equals stdout */ if ((filename == NULL) || (strcmp(filename->str, "-") == 0)) { output = stdout; @@ -504,15 +514,15 @@ int main(int argc, char **argv) g_string_free(filename, true); return 1; } - + fprintf(output, "%s\n",out); fclose(output); - + g_string_free(filename, true); - + if (out != NULL) free(out); } - + return(EXIT_SUCCESS); }