mmd-ruby 5.2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +78 -0
  3. data/MultiMarkdown-5/src/GLibFacade.c +310 -0
  4. data/MultiMarkdown-5/src/GLibFacade.h +100 -0
  5. data/MultiMarkdown-5/src/beamer.c +182 -0
  6. data/MultiMarkdown-5/src/beamer.h +11 -0
  7. data/MultiMarkdown-5/src/critic.c +117 -0
  8. data/MultiMarkdown-5/src/critic.h +15 -0
  9. data/MultiMarkdown-5/src/glib.h +11 -0
  10. data/MultiMarkdown-5/src/html.c +1171 -0
  11. data/MultiMarkdown-5/src/html.h +14 -0
  12. data/MultiMarkdown-5/src/latex.c +1234 -0
  13. data/MultiMarkdown-5/src/latex.h +16 -0
  14. data/MultiMarkdown-5/src/libMultiMarkdown.h +257 -0
  15. data/MultiMarkdown-5/src/lyx.c +2269 -0
  16. data/MultiMarkdown-5/src/lyx.h +37 -0
  17. data/MultiMarkdown-5/src/lyxbeamer.c +265 -0
  18. data/MultiMarkdown-5/src/lyxbeamer.h +11 -0
  19. data/MultiMarkdown-5/src/memoir.c +80 -0
  20. data/MultiMarkdown-5/src/memoir.h +10 -0
  21. data/MultiMarkdown-5/src/multimarkdown.c +559 -0
  22. data/MultiMarkdown-5/src/odf.c +1241 -0
  23. data/MultiMarkdown-5/src/odf.h +18 -0
  24. data/MultiMarkdown-5/src/opml.c +189 -0
  25. data/MultiMarkdown-5/src/opml.h +15 -0
  26. data/MultiMarkdown-5/src/parse_utilities.c +912 -0
  27. data/MultiMarkdown-5/src/parser.c +17341 -0
  28. data/MultiMarkdown-5/src/parser.h +190 -0
  29. data/MultiMarkdown-5/src/rng.c +117 -0
  30. data/MultiMarkdown-5/src/rtf.c +665 -0
  31. data/MultiMarkdown-5/src/rtf.h +17 -0
  32. data/MultiMarkdown-5/src/strtok.c +56 -0
  33. data/MultiMarkdown-5/src/strtok.h +9 -0
  34. data/MultiMarkdown-5/src/text.c +56 -0
  35. data/MultiMarkdown-5/src/text.h +11 -0
  36. data/MultiMarkdown-5/src/toc.c +157 -0
  37. data/MultiMarkdown-5/src/toc.h +15 -0
  38. data/MultiMarkdown-5/src/transclude.c +335 -0
  39. data/MultiMarkdown-5/src/transclude.h +28 -0
  40. data/MultiMarkdown-5/src/version.h +59 -0
  41. data/MultiMarkdown-5/src/writer.c +767 -0
  42. data/MultiMarkdown-5/src/writer.h +38 -0
  43. data/README.md +77 -0
  44. data/Rakefile +88 -0
  45. data/bin/mmd-ruby +123 -0
  46. data/ext/extconf.h +3 -0
  47. data/ext/extconf.rb +10 -0
  48. data/ext/multimarkdown.c +133 -0
  49. data/lib/mmd-jekyll.rb +19 -0
  50. data/lib/mmd-ruby.rb +1 -0
  51. data/lib/mmd.rb +1 -0
  52. data/lib/multimarkdown-ruby.rb +1 -0
  53. data/lib/multimarkdown.bundle +0 -0
  54. data/lib/multimarkdown.rb +69 -0
  55. data/lib/multimarkdown/version.rb +6 -0
  56. data/mmd-ruby.gemspec +37 -0
  57. data/test/extensions_test.rb +174 -0
  58. data/test/multimarkdown_test.rb +77 -0
  59. metadata +120 -0
@@ -0,0 +1,37 @@
1
+ #ifndef LYX_PARSER_H
2
+ #define LYX_PARSER_H
3
+
4
+ #include "parser.h"
5
+ #include "writer.h"
6
+
7
+ /* allow the user to change the heading levels */
8
+
9
+ extern GString *heading_name[7];
10
+
11
+ /* Lyx likes to wrap strings in "environments" */
12
+ enum lyx_environment{
13
+ LYX_NONE,
14
+ LYX_STANDARD,
15
+ LYX_CODE,
16
+ LYX_PLAIN
17
+ };
18
+
19
+
20
+ void perform_lyx_output(GString *out, node* list, scratch_pad *scratch);
21
+ bool begin_lyx_output(GString *out, node* list, scratch_pad *scratch);
22
+ void print_lyx_node_tree(GString *out, node *list, scratch_pad *scratch, bool no_newline);
23
+ void end_lyx_output(GString *out, node* list, scratch_pad *scratch);
24
+ void print_lyx_node(GString *out, node *n, scratch_pad *scratch, bool no_newline);
25
+ void print_lyx_localized_typography(GString *out, unsigned char character, scratch_pad *scratch);
26
+ void print_lyx_string(GString *out,char *str, scratch_pad *scratch,short environment);
27
+ void print_lyx_url(GString *out, char *str, scratch_pad *scratch);
28
+ void print_lyx_endnotes(GString *out, scratch_pad *scratch);
29
+ void lyx_get_table_dimensions(node* list, int *rows, int *cols, scratch_pad *scratch);
30
+ void add_prefixes(node *list, node *root, scratch_pad *scratch);
31
+ void update_links(char *label,char *prefix, scratch_pad *scratch);
32
+ char *prefix_label(char *prefix, char *label, bool pound);
33
+ void update_link_source(char *source, char *prefix,node *n);
34
+ void print_escaped_node_tree(GString *out, node *n);
35
+ void print_escaped_node(GString *out, node *n);
36
+ char * escape_string(char *str);
37
+ #endif
@@ -0,0 +1,265 @@
1
+ /*
2
+
3
+ lyxbeamer.c -- Beamer add-on to LyX writer
4
+
5
+ (c) 2013 Charles R. Cowan
6
+ (c) 2013 Fletcher T. Penney (http://fletcherpenney.net/).
7
+
8
+ Derrived from MultiMarkdown by Fletcher T. Penney - added code to support the LYY format directly
9
+
10
+ This program is free software; you can redistribute it and/or modify
11
+ it under the terms of the GNU General Public License or the MIT
12
+ license. See LICENSE for details.
13
+
14
+ This program is distributed in the hope that it will be useful,
15
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ GNU General Public License for more details.
18
+
19
+ */
20
+
21
+ #include "lyxbeamer.h"
22
+ #include "lyx.h"
23
+
24
+ bool need_fragile; // if the frame needs to be fragile
25
+
26
+ /* print_beamer_node_tree -- convert node tree to LyX */
27
+ void print_lyxbeamer_node_tree(GString *out, node *list, scratch_pad *scratch, bool no_newline) {
28
+ while (list != NULL) {
29
+ print_lyxbeamer_node(out, list, scratch, no_newline);
30
+ list = list->next;
31
+ }
32
+ }
33
+
34
+ /* print_beamer_node -- convert given node to LyX and append */
35
+ void print_lyxbeamer_node(GString *out, node *n, scratch_pad *scratch, bool no_newline) {
36
+ int lev;
37
+ int i;
38
+ char *temp;
39
+ char *prefixed_label;
40
+ node *temp_node;
41
+ int old_type;
42
+
43
+ /* If we are forcing a complete document, and METADATA isn't the first thing,
44
+ we need to close <head> */
45
+ if ((scratch->extensions & EXT_COMPLETE)
46
+ && !(scratch->extensions & EXT_HEAD_CLOSED) &&
47
+ !((n->key == FOOTER) || (n->key == METADATA))) {
48
+ scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED;
49
+ }
50
+ switch (n->key) {
51
+ case FOOTER:
52
+ if (scratch->lyx_in_frame){ // have an open frame
53
+ g_string_append(out,"\n\\end_deeper");
54
+ // g_string_append(out,"\n\\end_layout");
55
+ g_string_append(out, "\n\\begin_layout Separator");
56
+ g_string_append(out, "\n\\end_layout");
57
+ }
58
+ scratch->lyx_in_frame = FALSE;
59
+ print_lyxbeamer_endnotes(out, scratch);
60
+ break;
61
+ case BULLETLIST:
62
+ case ORDEREDLIST:
63
+ scratch -> lyx_beamerbullet = TRUE;
64
+ case DEFLIST:
65
+ old_type = scratch->lyx_para_type;
66
+ scratch->lyx_para_type = n->key;
67
+ scratch->lyx_level++;
68
+ if (scratch->lyx_level > 1){
69
+ g_string_append(out,"\n\\begin_deeper\n");
70
+ }
71
+ print_lyxbeamer_node_tree(out, n->children, scratch, FALSE);
72
+ scratch->lyx_level--;
73
+ if (scratch->lyx_level > 0){
74
+ g_string_append(out,"\n\\end_deeper\n");
75
+ }
76
+ scratch->lyx_para_type = old_type;
77
+ if (scratch->lyx_definition_open){
78
+ g_string_append(out,"\n\\end_deeper\n");
79
+ scratch->lyx_definition_open = FALSE;
80
+ }
81
+ break;
82
+ case LISTITEM:
83
+ temp_node = n-> children; // should be a list node
84
+ if (temp_node->key != LIST){
85
+ fprintf(stderr,"\nUnanticipated List Item Format");
86
+ exit(EXIT_FAILURE);
87
+ } else {
88
+ temp_node = temp_node-> children; // process the list
89
+ i = 0;
90
+ while (temp_node != NULL){
91
+ i++;
92
+ if (i == 2){
93
+ g_string_append(out,"\n\\begin_deeper\n");
94
+ old_type = scratch->lyx_para_type;
95
+ scratch->lyx_para_type = PARA; // and make it a paragraph, not a list item
96
+ }
97
+ print_lyx_node(out, temp_node, scratch, no_newline);
98
+ temp_node = temp_node->next;
99
+
100
+ }
101
+ if (i>1){
102
+ scratch->lyx_para_type = old_type; // reset the paragraph type
103
+ g_string_append(out,"\n\\end_deeper\n");
104
+ }
105
+ }
106
+ break;
107
+ case HEADINGSECTION:
108
+ if (scratch->lyx_in_frame){ // have an open frame
109
+ g_string_append(out,"\n\\end_deeper");
110
+ // g_string_append(out,"\n\\end_layout");
111
+ g_string_append(out, "\n\\begin_layout Separator");
112
+ g_string_append(out, "\n\\end_layout");
113
+ }
114
+ scratch->lyx_in_frame = FALSE;
115
+ need_fragile = FALSE;
116
+ if (tree_contains_key(n->children,VERBATIM)) {
117
+ need_fragile = TRUE;
118
+ }
119
+ print_lyxbeamer_node_tree(out,n->children,scratch , FALSE);
120
+ break;
121
+ case H1: case H2: case H3: case H4: case H5: case H6:
122
+ lev = n->key - H1 + scratch->baseheaderlevel; /* assumes H1 ... H6 are in order */
123
+ switch (lev) {
124
+ case 1:
125
+ g_string_append(out, "\n\\begin_layout Part\n");
126
+ break;
127
+ case 2:
128
+ g_string_append(out, "\n\\begin_layout Section\n");
129
+ break;
130
+ case 3:
131
+ if (need_fragile) {
132
+ g_string_append(out, "\n\\begin_layout FragileFrame");
133
+ } else {
134
+ g_string_append(out, "\n\\begin_layout Frame");
135
+ };
136
+ g_string_append(out,"\n\\begin_inset Argument 4");
137
+ g_string_append(out,"\nstatus open\n");
138
+ g_string_append(out,"\n\\begin_layout Plain Layout\n");
139
+ scratch->lyx_in_frame = TRUE;
140
+ break;
141
+ case 4:
142
+ g_string_append(out,"\n\\begin_layout Standard");
143
+ g_string_append(out, "\n\\begin_inset Flex ArticleMode");
144
+ g_string_append(out, "\nstatus open\n\n");
145
+ g_string_append(out,"\n\\begin_layout Plain Layout\n");
146
+ break;
147
+ default:
148
+ g_string_append(out,"\n\\begin_layout Standard");
149
+ g_string_append(out, "\n\\emph on\n");
150
+ break;
151
+ }
152
+ /* Don't allow footnotes */
153
+ scratch->no_lyx_footnote = TRUE;
154
+ if (n->children->key == AUTOLABEL) {
155
+ /* use label for header since one was specified (MMD)*/
156
+ temp = label_from_string(n->children->str);
157
+ prefixed_label = prefix_label(heading_name[lev-1]->str,temp,FALSE);
158
+ print_lyx_node_tree(out, n->children->next, scratch , FALSE);
159
+ g_string_append(out,"\n\\begin_inset CommandInset label\n");
160
+ g_string_append(out,"LatexCommand label\n");
161
+ g_string_append_printf(out, "name \"%s\"",prefixed_label);
162
+ g_string_append(out,"\n\\end_inset\n");
163
+ free(prefixed_label);
164
+ free(temp);
165
+ } else {
166
+ /* generate a label by default for MMD */
167
+ temp = label_from_node_tree(n->children);
168
+ prefixed_label = prefix_label(heading_name[lev-1]->str,temp,FALSE);
169
+ print_lyx_node_tree(out, n->children, scratch, FALSE);
170
+ g_string_append(out,"\n\\begin_inset CommandInset label\n");
171
+ g_string_append(out,"LatexCommand label\n");
172
+ g_string_append_printf(out, "name \"%s\"",prefixed_label);
173
+ g_string_append(out,"\n\\end_inset\n");
174
+ free(prefixed_label);
175
+ free(temp);
176
+ }
177
+ scratch->no_lyx_footnote = FALSE;
178
+ switch(lev){
179
+ case 1: case 2:
180
+ g_string_append(out,"\n\\end_layout\n");
181
+ break;
182
+ case 3:
183
+ g_string_append(out,"\n\\end_layout\n");
184
+ g_string_append(out,"\n\\end_inset\n");
185
+ g_string_append(out,"\n\\end_layout\n");
186
+ g_string_append(out,"\n\\begin_deeper\n");
187
+ break;
188
+ case 4:
189
+ g_string_append(out,"\n\\end_layout");
190
+ g_string_append(out,"\n\\end_inset");
191
+ g_string_append(out,"\n\\end_layout");
192
+ break;
193
+ default:
194
+ g_string_append(out, "\n\\emph default\n");
195
+ g_string_append(out,"\n\\end_layout");
196
+ break;
197
+ }
198
+
199
+ break;
200
+ default:
201
+ /* most things are not changed for beamer output */
202
+ print_lyx_node(out, n, scratch,no_newline);
203
+ }
204
+ }
205
+
206
+ /* print_beamer_endnotes */
207
+ void print_lyxbeamer_endnotes(GString *out, scratch_pad *scratch) {
208
+ node *temp_node;
209
+ scratch->used_notes = reverse_list(scratch->used_notes);
210
+ node *note = scratch->used_notes;
211
+
212
+ // Handle Glossary
213
+ temp_node = note;
214
+ while (temp_node != NULL){
215
+ if(temp_node->key == GLOSSARYSOURCE){
216
+ g_string_append(out, "\n\\begin_layout BeginFrame\nGlossary\n");
217
+ g_string_append(out,"\n\\begin_layout Standard");
218
+ g_string_append(out,"\n\\begin_inset CommandInset nomencl_print");
219
+ g_string_append(out,"\nLatexCommand printnomenclature");
220
+ g_string_append(out,"\nset_width \"auto\"\n");
221
+ g_string_append(out,"\n\\end_inset\n");
222
+ g_string_append(out,"\n\\end_layout\n");
223
+ g_string_append(out, "\n\\end_layout\n");
224
+ g_string_append(out, "\n\\begin_layout EndFrame");
225
+ g_string_append(out, "\n\\end_layout");
226
+ break;
227
+ }
228
+ temp_node = temp_node->next;
229
+ }
230
+
231
+ if (note == NULL)
232
+ return;
233
+
234
+ note = scratch->used_notes;
235
+
236
+ if (tree_contains_key(note,CITATIONSOURCE)){
237
+ g_string_append(out, "\n\\begin_layout BeginFrame\nReferences\n");
238
+ g_string_append(out, "\n\\end_layout");
239
+ }
240
+ while ( note != NULL) {
241
+ if (note->key == KEY_COUNTER) {
242
+ note = note->next;
243
+ continue;
244
+ }
245
+
246
+
247
+ if (note->key == CITATIONSOURCE) {
248
+ g_string_append(out, "\n\\begin_layout Bibliography\n");
249
+ g_string_append(out,"\\begin_inset CommandInset bibitem\n");
250
+ g_string_append(out,"LatexCommand bibitem\n");
251
+ g_string_append_printf(out, "key \"%s\"\n", note->str);
252
+ g_string_append_printf(out, "label \"%s\"\n", note->str);
253
+ g_string_append(out,"\n\\end_inset\n");
254
+ print_lyx_node(out, note, scratch, FALSE);
255
+ g_string_append(out,"\n\\end_layout\n");
256
+ } else {
257
+ /* footnotes handled elsewhere */
258
+ }
259
+
260
+ note = note->next;
261
+ }
262
+ g_string_append(out, "\n\\begin_layout EndFrame"); // close last frame
263
+ g_string_append(out, "\n\\end_layout");
264
+
265
+ }
@@ -0,0 +1,11 @@
1
+ #ifndef LYX_BEAMER_PARSER_H
2
+ #define LYX_BEAMER_PARSER_H
3
+
4
+ #include "parser.h"
5
+ #include "lyx.h"
6
+
7
+ void print_lyxbeamer_node_tree(GString *out, node *list, scratch_pad *scratch,bool no_newline);
8
+ void print_lyxbeamer_node(GString *out, node *n, scratch_pad *scratch,bool no_newline);
9
+ void print_lyxbeamer_endnotes(GString *out, scratch_pad *scratch);
10
+
11
+ #endif
@@ -0,0 +1,80 @@
1
+ /*
2
+
3
+ memoir.c -- Memoir add-on to LaTeX writer
4
+
5
+ (c) 2013-2016 Fletcher T. Penney (http://fletcherpenney.net/).
6
+
7
+ This program is free software; you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License or the MIT
9
+ license. See LICENSE for details.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ */
17
+
18
+ #include "memoir.h"
19
+
20
+ /* print_memoir_node_tree -- convert node tree to LaTeX */
21
+ void print_memoir_node_tree(GString *out, node *list, scratch_pad *scratch) {
22
+ while (list != NULL) {
23
+ print_memoir_node(out, list, scratch);
24
+ list = list->next;
25
+ }
26
+ }
27
+
28
+ /* print_memoir_node -- convert given node to LaTeX and append */
29
+ void print_memoir_node(GString *out, node *n, scratch_pad *scratch) {
30
+
31
+ /* If we are forcing a complete document, and METADATA isn't the first thing,
32
+ we need to close <head> */
33
+ if ((scratch->extensions & EXT_COMPLETE)
34
+ && !(scratch->extensions & EXT_HEAD_CLOSED) &&
35
+ !((n->key == FOOTER) || (n->key == METADATA))) {
36
+ pad(out, 2, scratch);
37
+ scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED;
38
+ }
39
+ switch (n->key) {
40
+ case VERBATIM:
41
+ case VERBATIMFENCE:
42
+ pad(out, 2, scratch);
43
+ if ((n->children != NULL) && (n->children->key == VERBATIMTYPE)) {
44
+ trim_trailing_whitespace(n->children->str);
45
+ if (strlen(n->children->str) > 0) {
46
+ g_string_append_printf(out, "\\begin{adjustwidth}{2.5em}{2.5em}\n\\begin{lstlisting}[language=%s]\n", n->children->str);
47
+ print_raw_node(out, n);
48
+ g_string_append_printf(out, "\n\\end{lstlisting}\n\\end{adjustwidth}");
49
+ scratch->padded = 0;
50
+ break;
51
+ }
52
+ }
53
+ g_string_append_printf(out, "\\begin{adjustwidth}{2.5em}{2.5em}\n\\begin{verbatim}\n\n");
54
+ print_raw_node(out, n);
55
+ g_string_append_printf(out, "\n\\end{verbatim}\n\\end{adjustwidth}");
56
+ scratch->padded = 0;
57
+ break;
58
+ case HEADINGSECTION:
59
+ print_memoir_node_tree(out, n->children, scratch);
60
+ break;
61
+ case DEFLIST:
62
+ pad(out, 2, scratch);
63
+ g_string_append_printf(out, "\\begin{description}");
64
+ scratch->padded = 0;
65
+ print_memoir_node_tree(out, n->children, scratch);
66
+ pad(out, 1, scratch);
67
+ g_string_append_printf(out, "\\end{description}");
68
+ scratch->padded = 0;
69
+ break;
70
+ case DEFINITION:
71
+ pad(out, 2, scratch);
72
+ scratch->padded = 2;
73
+ print_memoir_node_tree(out, n->children, scratch);
74
+ scratch->padded = 0;
75
+ break;
76
+ default:
77
+ /* most things are not changed for memoir output */
78
+ print_latex_node(out, n, scratch);
79
+ }
80
+ }
@@ -0,0 +1,10 @@
1
+ #ifndef MEMOIR_PARSER_H
2
+ #define MEMOIR_PARSER_H
3
+
4
+ #include "parser.h"
5
+ #include "latex.h"
6
+
7
+ void print_memoir_node_tree(GString *out, node *list, scratch_pad *scratch);
8
+ void print_memoir_node(GString *out, node *n, scratch_pad *scratch);
9
+
10
+ #endif
@@ -0,0 +1,559 @@
1
+ /**
2
+
3
+ MultiMarkdown
4
+
5
+ @file multimarkdown.c
6
+
7
+ @brief MultiMarkdown - lightweight markup processor
8
+
9
+ This file provides the command line executable wrapper for the
10
+ libMultiMarkdown library. It handles parsing arguments to determine
11
+ which options and formats are needed, as well as providing file
12
+ locations to support file transclusion.
13
+
14
+ @author Fletcher T. Penney
15
+ @bug No known bugs
16
+
17
+ **/
18
+
19
+ /*
20
+
21
+ Copyright © 2013-2016 Fletcher T. Penney.
22
+
23
+ MultiMarkdown 4 and 5 are derived from peg-multimarkdown, which was
24
+ forked from peg-markdown, which is (c) 2008 John MacFarlane
25
+ (jgm at berkeley dot edu), and licensed under GNU GPL or MIT.
26
+
27
+
28
+ The `c-template` project is released under the MIT License.
29
+
30
+
31
+ MMD 5 is released under the MIT License.
32
+
33
+
34
+ CuTest is released under the zlib/libpng license. See CuTest.c for the text
35
+ of the license.
36
+
37
+
38
+ ## The MIT License ##
39
+
40
+ Permission is hereby granted, free of charge, to any person obtaining a copy
41
+ of this software and associated documentation files (the "Software"), to deal
42
+ in the Software without restriction, including without limitation the rights
43
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
44
+ copies of the Software, and to permit persons to whom the Software is
45
+ furnished to do so, subject to the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be included in
48
+ all copies or substantial portions of the Software.
49
+
50
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
51
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
52
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
53
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
54
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
55
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
56
+ THE SOFTWARE.
57
+
58
+ */
59
+
60
+
61
+ #include <getopt.h>
62
+ #include <libgen.h>
63
+ #include "parser.h"
64
+ #include "transclude.h"
65
+ #include "version.h"
66
+
67
+ /// main()
68
+ int main(int argc, char **argv)
69
+ {
70
+ int numargs;
71
+ int c;
72
+ int i;
73
+ static int batch_flag = 0;
74
+ static int complete_flag = 0;
75
+ static int snippet_flag = 0;
76
+ static int compatibility_flag = 0;
77
+ static int notes_flag = 0;
78
+ static int no_notes_flag = 0;
79
+ static int typography_flag = 0;
80
+ static int no_typography_flag = 0;
81
+ static int label_flag = 0;
82
+ static int no_label_flag = 0;
83
+ static int escaped_line_breaks_flag = 0;
84
+ static int obfuscate_flag = 0;
85
+ static int no_obfuscate_flag = 0;
86
+ static int process_html_flag = 0;
87
+ static int random_footnotes_flag = 0;
88
+ bool list_meta_keys = 0;
89
+ bool list_transclude_manifest = 0;
90
+ char *target_meta_key = FALSE;
91
+
92
+ static struct option long_options[] = {
93
+ {"batch", no_argument, &batch_flag, 1}, /* process each file separately */
94
+ {"to", required_argument, 0, 't'}, /* which output format to use */
95
+ {"full", no_argument, &complete_flag, 1}, /* complete document */
96
+ {"snippet", no_argument, &snippet_flag, 1}, /* snippet only */
97
+ {"output", required_argument, 0, 'o'}, /* which output format to use */
98
+ {"notes", no_argument, &notes_flag, 1}, /* use footnotes */
99
+ {"nonotes", no_argument, &no_notes_flag, 1}, /* don't use footnotes */
100
+ {"smart", no_argument, &typography_flag, 1}, /* use smart typography */
101
+ {"nosmart", no_argument, &no_typography_flag, 1}, /* don't use smart typography */
102
+ {"mask", no_argument, &obfuscate_flag, 1}, /* mask email addresses */
103
+ {"nomask", no_argument, &no_obfuscate_flag, 1}, /* don't mask email addresses */
104
+ {"labels", no_argument, &label_flag, 1}, /* generate labels */
105
+ {"nolabels", no_argument, &no_label_flag, 1}, /* don't generate labels */
106
+ {"escaped-line-breaks", no_argument, &escaped_line_breaks_flag, 1}, /* enable escaped line breaks */
107
+ {"compatibility", no_argument, &compatibility_flag, 1}, /* compatibility mode */
108
+ {"process-html", no_argument, &process_html_flag, 1}, /* process Markdown inside HTML */
109
+ {"random", no_argument, &random_footnotes_flag, 1}, /* Use random numbers for footnote links */
110
+ {"accept", no_argument, 0, 'a'}, /* Accept all proposed CriticMarkup changes */
111
+ {"reject", no_argument, 0, 'r'}, /* Reject all proposed CriticMarkup changes */
112
+ {"metadata-keys", no_argument, 0, 'm'}, /* List all metadata keys */
113
+ {"extract", required_argument, 0, 'e'}, /* show value of specified metadata */
114
+ {"version", no_argument, 0, 'v'}, /* display version information */
115
+ {"help", no_argument, 0, 'h'}, /* display usage information */
116
+ {"manifest", no_argument, 0, 'x'}, /* List all transcluded files */
117
+ {NULL, 0, NULL, 0}
118
+ };
119
+
120
+ GString *inputbuf;
121
+ GString *manifest;
122
+ FILE *input;
123
+ FILE *output;
124
+ int curchar;
125
+ GString *filename = NULL;
126
+
127
+ char *out;
128
+
129
+ /* set up my data for the parser */
130
+ int output_format = HTML_FORMAT; /* Default output format unless specified otherwise */
131
+ unsigned long extensions = 0;
132
+ extensions = extensions | EXT_SMART | EXT_NOTES | EXT_OBFUSCATE;
133
+
134
+ /* process options */
135
+ while (1) {
136
+ int option_index = 0;
137
+
138
+ c = getopt_long (argc, argv, "vhco:bfst:me:arx", long_options, &option_index);
139
+
140
+ if (c == -1)
141
+ break;
142
+
143
+ switch (c) {
144
+ case 0: /* handle long_options */
145
+ /* printf ("option %s", long_options[option_index].name);
146
+ if (optarg)
147
+ printf (" with arg %s", optarg);
148
+ printf("\n"); */
149
+ break;
150
+
151
+ case 'b': /* batch */
152
+ batch_flag = 1;
153
+ break;
154
+
155
+ case 'c': /* compatibility */
156
+ compatibility_flag = 1;
157
+ break;
158
+
159
+ case 'o': /* output filename */
160
+ if (optarg)
161
+ filename = g_string_new(optarg);
162
+ break;
163
+
164
+ case 'v': /* show version */
165
+ printf("\nMultiMarkdown version %s\n%s\n",MULTIMARKDOWN_VERSION, MMD_COPYRIGHT);
166
+ return(EXIT_SUCCESS);
167
+
168
+ case 'h': /* show usage */
169
+ printf("\nMultiMarkdown version %s\n\n",MULTIMARKDOWN_VERSION);
170
+ printf(" %s [OPTION...] [FILE...]\n",argv[0]);
171
+ printf("\n"
172
+ " Options:\n"
173
+ " -h, --help Show help\n"
174
+ " -v, --version Show version information\n"
175
+ " -o, --output=FILE Send output to FILE\n"
176
+ " -t, --to=FORMAT Convert to FORMAT\n"
177
+ " -b, --batch Process each file separately\n"
178
+ " -c, --compatibility Markdown compatibility mode\n"
179
+ " -f, --full Force a complete document\n"
180
+ " -s, --snippet Force a snippet\n"
181
+ " --process-html Process Markdown inside of raw HTML\n"
182
+ " -m, --metadata-keys List all metadata keys\n"
183
+ " -e, --extract Extract specified metadata\n"
184
+ " -x, --manifest Show manifest of all transcluded files\n"
185
+ " --random Use random numbers for footnote anchors\n"
186
+ "\n"
187
+ " -a, --accept Accept all CriticMarkup changes\n"
188
+ " -r, --reject Reject all CriticMarkup changes\n"
189
+ "\n"
190
+ " --smart, --nosmart Toggle smart typography\n"
191
+ " --notes, --nonotes Toggle footnotes\n"
192
+ " --labels, --nolabels Disable id attributes for headers\n"
193
+ " --mask, --nomask Mask email addresses in HTML\n"
194
+ " --escaped-line-breaks Enable escaped line breaks\n"
195
+
196
+ "\nAvailable FORMATs: html(default), latex, beamer, memoir, odf, opml, lyx, mmd\n\n"
197
+ "NOTE: The lyx output format was created by Charles R. Cowan, and \n\tis provided as is.\n\n\n"
198
+ );
199
+ return(EXIT_SUCCESS);
200
+
201
+ case 't': /* output format */
202
+ if (strcmp(optarg, "text") == 0)
203
+ output_format = TEXT_FORMAT;
204
+ else if (strcmp(optarg, "html") == 0)
205
+ output_format = HTML_FORMAT;
206
+ else if (strcmp(optarg, "latex") == 0)
207
+ output_format = LATEX_FORMAT;
208
+ else if (strcmp(optarg, "memoir") == 0)
209
+ output_format = MEMOIR_FORMAT;
210
+ else if (strcmp(optarg, "beamer") == 0)
211
+ output_format = BEAMER_FORMAT;
212
+ else if (strcmp(optarg, "opml") == 0)
213
+ output_format = OPML_FORMAT;
214
+ else if (strcmp(optarg, "odf") == 0)
215
+ output_format = ODF_FORMAT;
216
+ else if (strcmp(optarg, "rtf") == 0)
217
+ output_format = RTF_FORMAT;
218
+ else if (strcmp(optarg, "lyx") == 0)
219
+ output_format = LYX_FORMAT;
220
+ else if (strcmp(optarg, "mmd") == 0)
221
+ output_format = ORIGINAL_FORMAT;
222
+ else {
223
+ /* no valid format specified */
224
+ fprintf(stderr, "%s: Unknown output format '%s'\n",argv[0], optarg);
225
+ exit(EXIT_FAILURE);
226
+ }
227
+ break;
228
+
229
+ case 'f': /* full doc */
230
+ extensions = extensions | EXT_COMPLETE;
231
+ break;
232
+
233
+ case 's': /* snippet only */
234
+ extensions = extensions | EXT_SNIPPET;
235
+ break;
236
+
237
+ case 'm': /* list metadata */
238
+ list_meta_keys = 1;
239
+ break;
240
+
241
+ case 'e': /* extract metadata */
242
+ target_meta_key = strdup(optarg);
243
+ break;
244
+
245
+ case '?': /* long handles */
246
+ break;
247
+
248
+ case 'a': /* Accept CriticMarkup changes */
249
+ extensions = extensions | EXT_CRITIC_ACCEPT;
250
+ break;
251
+
252
+ case 'r': /* Reject CriticMarkup changes */
253
+ extensions = extensions | EXT_CRITIC_REJECT;
254
+ break;
255
+
256
+ case 'x': /* List transcluded files */
257
+ list_transclude_manifest = 1;
258
+ break;
259
+
260
+ default:
261
+ fprintf(stderr,"Error parsing options.\n");
262
+ abort();
263
+ }
264
+ }
265
+
266
+ /* Compatibility mode emulates the behavior of Markdown.pl */
267
+ if (compatibility_flag) {
268
+ extensions = 0x000000;
269
+ extensions = extensions | EXT_COMPATIBILITY | EXT_NO_LABELS | EXT_OBFUSCATE;
270
+ }
271
+
272
+ /* apply extensions from long options*/
273
+ if (complete_flag)
274
+ extensions = extensions | EXT_COMPLETE;
275
+
276
+ if (snippet_flag)
277
+ extensions = extensions | EXT_SNIPPET;
278
+
279
+ if (notes_flag)
280
+ extensions = extensions | EXT_NOTES;
281
+
282
+ if (no_notes_flag)
283
+ extensions &= ~EXT_NOTES;
284
+
285
+ if (typography_flag)
286
+ extensions = extensions | EXT_SMART;
287
+
288
+ if (no_typography_flag)
289
+ extensions &= ~EXT_SMART;
290
+
291
+ if (label_flag)
292
+ extensions &= ~EXT_NO_LABELS;
293
+
294
+ if (no_label_flag)
295
+ extensions = extensions | EXT_NO_LABELS;
296
+
297
+ if (obfuscate_flag)
298
+ extensions = extensions | EXT_OBFUSCATE;
299
+
300
+ if (no_obfuscate_flag)
301
+ extensions &= ~EXT_OBFUSCATE;
302
+
303
+ if (process_html_flag)
304
+ extensions = extensions | EXT_PROCESS_HTML;
305
+
306
+ if (random_footnotes_flag)
307
+ extensions = extensions | EXT_RANDOM_FOOT;
308
+
309
+ if (escaped_line_breaks_flag)
310
+ extensions = extensions | EXT_ESCAPED_LINE_BREAKS;
311
+
312
+ /* Enable HEADINGSECTION for certain formats */
313
+ if ((output_format == OPML_FORMAT) || (output_format == BEAMER_FORMAT) || (output_format == LYX_FORMAT))
314
+ extensions = extensions | EXT_HEADINGSECTION;
315
+
316
+ /* fix numbering to account for options */
317
+ argc -= optind;
318
+ argv += optind;
319
+
320
+ /* We expect argc and argv to still point just one below the start of remaining args */
321
+ argc++;
322
+ argv--;
323
+
324
+ /* any filenames */
325
+ numargs = argc -1;
326
+
327
+ if (batch_flag && (numargs != 0)) {
328
+ /* we have multiple file names -- handle individually */
329
+
330
+ for (i = 0; i < numargs; i++) {
331
+ inputbuf = g_string_new("");
332
+ manifest = g_string_new("");
333
+ char *temp = NULL;
334
+ char *folder = NULL;
335
+
336
+ /* Read file */
337
+ if ((input = fopen(argv[i+1], "r")) == NULL ) {
338
+ perror(argv[i+1]);
339
+ g_string_free(inputbuf, true);
340
+ g_string_free(filename, true);
341
+ exit(EXIT_FAILURE);
342
+ }
343
+
344
+ while ((curchar = fgetc(input)) != EOF)
345
+ g_string_append_c(inputbuf, curchar);
346
+ fclose(input);
347
+
348
+ /* list metadata keys */
349
+ if (list_meta_keys) {
350
+ out = extract_metadata_keys(inputbuf->str, extensions);
351
+ if (out != NULL) {
352
+ fprintf(stdout, "%s", out);
353
+ free(out);
354
+ g_string_free(inputbuf, true);
355
+ free(target_meta_key);
356
+ return(EXIT_SUCCESS);
357
+ }
358
+ }
359
+
360
+ /* extract metadata */
361
+ if (target_meta_key) {
362
+ out = extract_metadata_value(inputbuf->str, extensions, target_meta_key);
363
+ if (out != NULL)
364
+ fprintf(stdout, "%s\n", out);
365
+ free(out);
366
+ g_string_free(inputbuf, true);
367
+ free(target_meta_key);
368
+ return(EXIT_SUCCESS);
369
+ }
370
+
371
+ if (!(extensions & EXT_COMPATIBILITY)) {
372
+ temp = strdup(argv[i+1]);
373
+ folder = dirname(temp);
374
+ prepend_mmd_header(inputbuf);
375
+ append_mmd_footer(inputbuf);
376
+ transclude_source(inputbuf, folder, NULL, output_format, manifest);
377
+ free(temp);
378
+ // free(folder);
379
+ }
380
+
381
+ /* list transclude manifest */
382
+ if (list_transclude_manifest) {
383
+ fprintf(stdout, "%s\n", manifest->str);
384
+ g_string_free(inputbuf, true);
385
+ g_string_free(manifest, true);
386
+ return(EXIT_SUCCESS);
387
+ } else {
388
+ g_string_free(manifest, true);
389
+ }
390
+
391
+ if (output_format == ORIGINAL_FORMAT) {
392
+ /* We want the source, don't parse */
393
+ out = (inputbuf->str);
394
+ g_string_free(inputbuf, FALSE);
395
+ } else {
396
+ out = markdown_to_string(inputbuf->str, extensions, output_format);
397
+ g_string_free(inputbuf, true);
398
+ }
399
+
400
+ /* set up for output */
401
+ temp = argv[i+1]; /* get current filename */
402
+ if (strrchr(temp,'.') != NULL) {
403
+ long count = strrchr(temp,'.') - temp;
404
+ if (count != 0) {
405
+ /* truncate string at "." */
406
+ temp[count] = '\0';
407
+ }
408
+ }
409
+
410
+ filename = g_string_new(temp);
411
+
412
+ if (output_format == TEXT_FORMAT) {
413
+ g_string_append(filename,".txt");
414
+ } else if (output_format == HTML_FORMAT) {
415
+ g_string_append(filename,".html");
416
+ } else if (output_format == LATEX_FORMAT) {
417
+ g_string_append(filename,".tex");
418
+ } else if (output_format == BEAMER_FORMAT) {
419
+ g_string_append(filename,".tex");
420
+ } else if (output_format == MEMOIR_FORMAT) {
421
+ g_string_append(filename,".tex");
422
+ } else if (output_format == ODF_FORMAT) {
423
+ g_string_append(filename,".fodt");
424
+ } else if (output_format == OPML_FORMAT) {
425
+ g_string_append(filename,".opml");
426
+ } else if (output_format == LYX_FORMAT) {
427
+ g_string_append(filename,".lyx");
428
+ } else if (output_format == RTF_FORMAT) {
429
+ g_string_append(filename,".rtf");
430
+ } else if (output_format == ORIGINAL_FORMAT) {
431
+ g_string_append(filename,".mmd_out");
432
+ } else {
433
+ /* default extension -- in this case we only have 1 */
434
+ g_string_append(filename,".txt");
435
+ }
436
+
437
+ if (!(output = fopen(filename->str, "w"))) {
438
+ perror(filename->str);
439
+ } else {
440
+ fprintf(output, "%s\n",out);
441
+ fclose(output);
442
+ }
443
+
444
+ g_string_free(filename,true);
445
+
446
+ if (out != NULL)
447
+ free(out);
448
+ }
449
+ } else {
450
+ /* get input from stdin or concat all files */
451
+ inputbuf = g_string_new("");
452
+ char *folder = NULL;
453
+ char *temp = NULL;
454
+ GString *manifest = g_string_new("");
455
+
456
+ folder = getcwd(0,0);
457
+
458
+ if (numargs == 0) {
459
+ /* get stdin */
460
+ while ((curchar = fgetc(stdin)) != EOF)
461
+ g_string_append_c(inputbuf, curchar);
462
+ fclose(stdin);
463
+ } else {
464
+ /* get files */
465
+ free(folder);
466
+ temp = strdup(argv[1]);
467
+ folder = dirname(temp);
468
+
469
+ for (i = 0; i < numargs; i++) {
470
+ if ((input = fopen(argv[i+1], "r")) == NULL ) {
471
+ perror(argv[i+1]);
472
+ g_string_free(inputbuf, true);
473
+ g_string_free(filename, true);
474
+ // free(folder);
475
+ free(temp);
476
+ exit(EXIT_FAILURE);
477
+ }
478
+
479
+ while ((curchar = fgetc(input)) != EOF)
480
+ g_string_append_c(inputbuf, curchar);
481
+ fclose(input);
482
+ }
483
+ }
484
+
485
+ if (!(extensions & EXT_COMPATIBILITY)) {
486
+ prepend_mmd_header(inputbuf);
487
+ append_mmd_footer(inputbuf);
488
+ transclude_source(inputbuf, folder, NULL, output_format, manifest);
489
+ }
490
+
491
+ free(temp);
492
+
493
+ //if (folder != NULL)
494
+ // free(folder);
495
+
496
+ /* list metadata keys */
497
+ if (list_meta_keys) {
498
+ out = extract_metadata_keys(inputbuf->str, extensions);
499
+ if (out != NULL) {
500
+ fprintf(stdout, "%s", out);
501
+ free(out);
502
+ g_string_free(inputbuf, true);
503
+ free(target_meta_key);
504
+ return(EXIT_SUCCESS);
505
+ }
506
+ }
507
+
508
+ /* extract metadata */
509
+ if (target_meta_key) {
510
+ out = extract_metadata_value(inputbuf->str, extensions, target_meta_key);
511
+ if (out != NULL)
512
+ fprintf(stdout, "%s\n", out);
513
+ free(out);
514
+ g_string_free(inputbuf, true);
515
+ free(target_meta_key);
516
+ return(EXIT_SUCCESS);
517
+ }
518
+
519
+ /* list transclude manifest */
520
+ if (list_transclude_manifest) {
521
+ fprintf(stdout, "%s\n", manifest->str);
522
+ g_string_free(inputbuf, true);
523
+ g_string_free(manifest, true);
524
+ return(EXIT_SUCCESS);
525
+ } else {
526
+ g_string_free(manifest, true);
527
+ }
528
+
529
+ if (output_format == ORIGINAL_FORMAT) {
530
+ /* We want the source, don't parse */
531
+ out = (inputbuf->str);
532
+ g_string_free(inputbuf, FALSE);
533
+ } else {
534
+ out = markdown_to_string(inputbuf->str, extensions, output_format);
535
+ g_string_free(inputbuf, true);
536
+ }
537
+
538
+ /* did we specify an output filename; "-" equals stdout */
539
+ if ((filename == NULL) || (strcmp(filename->str, "-") == 0)) {
540
+ output = stdout;
541
+ } else if (!(output = fopen(filename->str, "w"))) {
542
+ perror(filename->str);
543
+ if (out != NULL)
544
+ free(out);
545
+ g_string_free(filename, true);
546
+ return 1;
547
+ }
548
+
549
+ fprintf(output, "%s\n",out);
550
+ fclose(output);
551
+
552
+ g_string_free(filename, true);
553
+
554
+ if (out != NULL)
555
+ free(out);
556
+ }
557
+
558
+ return(EXIT_SUCCESS);
559
+ }