multimarkdown 4.5.0.r1
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.
- data/LICENSE +75 -0
- data/MultiMarkdown-4/GLibFacade.c +294 -0
- data/MultiMarkdown-4/GLibFacade.h +95 -0
- data/MultiMarkdown-4/beamer.c +179 -0
- data/MultiMarkdown-4/beamer.h +11 -0
- data/MultiMarkdown-4/critic.c +111 -0
- data/MultiMarkdown-4/critic.h +15 -0
- data/MultiMarkdown-4/glib.h +11 -0
- data/MultiMarkdown-4/html.c +1060 -0
- data/MultiMarkdown-4/html.h +14 -0
- data/MultiMarkdown-4/latex.c +1137 -0
- data/MultiMarkdown-4/latex.h +16 -0
- data/MultiMarkdown-4/libMultiMarkdown.h +156 -0
- data/MultiMarkdown-4/lyx.c +2163 -0
- data/MultiMarkdown-4/lyx.h +36 -0
- data/MultiMarkdown-4/lyxbeamer.c +267 -0
- data/MultiMarkdown-4/lyxbeamer.h +11 -0
- data/MultiMarkdown-4/memoir.c +79 -0
- data/MultiMarkdown-4/memoir.h +10 -0
- data/MultiMarkdown-4/multimarkdown.c +483 -0
- data/MultiMarkdown-4/odf.c +1201 -0
- data/MultiMarkdown-4/odf.h +18 -0
- data/MultiMarkdown-4/opml.c +188 -0
- data/MultiMarkdown-4/opml.h +15 -0
- data/MultiMarkdown-4/parse_utilities.c +752 -0
- data/MultiMarkdown-4/parser.c +15582 -0
- data/MultiMarkdown-4/parser.h +186 -0
- data/MultiMarkdown-4/rng.c +117 -0
- data/MultiMarkdown-4/rtf.c +648 -0
- data/MultiMarkdown-4/rtf.h +17 -0
- data/MultiMarkdown-4/strtok.c +56 -0
- data/MultiMarkdown-4/strtok.h +9 -0
- data/MultiMarkdown-4/text.c +53 -0
- data/MultiMarkdown-4/text.h +11 -0
- data/MultiMarkdown-4/transclude.c +213 -0
- data/MultiMarkdown-4/transclude.h +26 -0
- data/MultiMarkdown-4/writer.c +576 -0
- data/MultiMarkdown-4/writer.h +34 -0
- data/README.md +70 -0
- data/Rakefile +85 -0
- data/bin/ruby_multi_markdown +128 -0
- data/ext/extconf.h +3 -0
- data/ext/extconf.rb +17 -0
- data/ext/multi_markdown.c +100 -0
- data/lib/multi_markdown.bundle +0 -0
- data/lib/multi_markdown.rb +88 -0
- data/lib/multi_markdown/version.rb +6 -0
- data/lib/multimarkdown.rb +1 -0
- data/multi_markdown.gemspec +37 -0
- data/test/multi_markdown_test.rb +64 -0
- metadata +119 -0
@@ -0,0 +1,36 @@
|
|
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
|
+
#endif
|
@@ -0,0 +1,267 @@
|
|
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
|
+
/* print_beamer_node_tree -- convert node tree to LyX */
|
25
|
+
void print_lyxbeamer_node_tree(GString *out, node *list, scratch_pad *scratch, bool no_newline) {
|
26
|
+
while (list != NULL) {
|
27
|
+
print_lyxbeamer_node(out, list, scratch, no_newline);
|
28
|
+
list = list->next;
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
/* print_beamer_node -- convert given node to LyX and append */
|
33
|
+
void print_lyxbeamer_node(GString *out, node *n, scratch_pad *scratch, bool no_newline) {
|
34
|
+
int lev;
|
35
|
+
int i;
|
36
|
+
char *temp;
|
37
|
+
char *prefixed_label;
|
38
|
+
node *temp_node;
|
39
|
+
int old_type;
|
40
|
+
|
41
|
+
/* If we are forcing a complete document, and METADATA isn't the first thing,
|
42
|
+
we need to close <head> */
|
43
|
+
if ((scratch->extensions & EXT_COMPLETE)
|
44
|
+
&& !(scratch->extensions & EXT_HEAD_CLOSED) &&
|
45
|
+
!((n->key == FOOTER) || (n->key == METADATA))) {
|
46
|
+
scratch->extensions = scratch->extensions | EXT_HEAD_CLOSED;
|
47
|
+
}
|
48
|
+
switch (n->key) {
|
49
|
+
case FOOTER:
|
50
|
+
if (scratch->lyx_fragile){ // have an open fragile
|
51
|
+
g_string_append(out,"\n\\end_inset");
|
52
|
+
g_string_append(out,"\n\\end_layout");
|
53
|
+
}
|
54
|
+
scratch->lyx_fragile = FALSE;
|
55
|
+
print_lyxbeamer_endnotes(out, scratch);
|
56
|
+
break;
|
57
|
+
case BULLETLIST:
|
58
|
+
case ORDEREDLIST:
|
59
|
+
case DEFLIST:
|
60
|
+
old_type = scratch->lyx_para_type;
|
61
|
+
scratch->lyx_para_type = n->key;
|
62
|
+
scratch->lyx_level++;
|
63
|
+
if (scratch->lyx_level > 1){
|
64
|
+
g_string_append(out,"\n\\begin_deeper\n");
|
65
|
+
}
|
66
|
+
print_lyxbeamer_node_tree(out, n->children, scratch, FALSE);
|
67
|
+
scratch->lyx_level--;
|
68
|
+
if (scratch->lyx_level > 0){
|
69
|
+
g_string_append(out,"\n\\end_deeper\n");
|
70
|
+
}
|
71
|
+
scratch->lyx_para_type = old_type;
|
72
|
+
if (scratch->lyx_definition_open){
|
73
|
+
g_string_append(out,"\n\\end_deeper\n");
|
74
|
+
scratch->lyx_definition_open = FALSE;
|
75
|
+
}
|
76
|
+
break;
|
77
|
+
case LISTITEM:
|
78
|
+
scratch-> lyx_beamerbullet = TRUE;
|
79
|
+
temp_node = n-> children; // should be a list node
|
80
|
+
if (temp_node->key != LIST){
|
81
|
+
fprintf(stderr,"\nUnanticipated List Item Format");
|
82
|
+
exit(EXIT_FAILURE);
|
83
|
+
} else {
|
84
|
+
temp_node = temp_node-> children; // process the list
|
85
|
+
i = 0;
|
86
|
+
while (temp_node != NULL){
|
87
|
+
i++;
|
88
|
+
if (i == 2){
|
89
|
+
g_string_append(out,"\n\\begin_deeper\n");
|
90
|
+
old_type = scratch->lyx_para_type;
|
91
|
+
scratch->lyx_para_type = PARA; // and make it a paragraph, not a list item
|
92
|
+
}
|
93
|
+
print_lyx_node(out, temp_node, scratch, no_newline);
|
94
|
+
temp_node = temp_node->next;
|
95
|
+
|
96
|
+
}
|
97
|
+
if (i>1){
|
98
|
+
scratch->lyx_para_type = old_type; // reset the paragraph type
|
99
|
+
g_string_append(out,"\n\\end_deeper\n");
|
100
|
+
}
|
101
|
+
}
|
102
|
+
scratch-> lyx_beamerbullet = TRUE;
|
103
|
+
break;
|
104
|
+
case HEADINGSECTION:
|
105
|
+
if (scratch->lyx_fragile){ // have an open fragile
|
106
|
+
g_string_append(out,"\n\\end_inset");
|
107
|
+
g_string_append(out,"\n\\end_layout");
|
108
|
+
}
|
109
|
+
scratch->lyx_fragile = FALSE;
|
110
|
+
if (tree_contains_key(n->children,VERBATIM)) {
|
111
|
+
scratch->lyx_fragile = TRUE;
|
112
|
+
}
|
113
|
+
print_lyxbeamer_node_tree(out,n->children,scratch , FALSE);
|
114
|
+
break;
|
115
|
+
case H1: case H2: case H3: case H4: case H5: case H6:
|
116
|
+
lev = n->key - H1 + scratch->baseheaderlevel; /* assumes H1 ... H6 are in order */
|
117
|
+
switch (lev) {
|
118
|
+
case 1:
|
119
|
+
g_string_append(out, "\n\\begin_layout Part\n");
|
120
|
+
break;
|
121
|
+
case 2:
|
122
|
+
g_string_append(out, "\n\\begin_layout Section\n");
|
123
|
+
break;
|
124
|
+
case 3:
|
125
|
+
if (scratch->lyx_fragile) {
|
126
|
+
g_string_append(out, "\n\\begin_layout EndFrame");
|
127
|
+
g_string_append(out, "\n\\end_layout");
|
128
|
+
g_string_append(out, "\n\\begin_layout Standard");
|
129
|
+
g_string_append(out,"\n\\begin_inset Flex FragileFrame");
|
130
|
+
g_string_append(out,"\nstatus open\n\n");
|
131
|
+
g_string_append(out,"\n\\begin_layout Plain Layout\n");
|
132
|
+
g_string_append(out,"\n\\begin_inset Flex FragileTitle");
|
133
|
+
g_string_append(out,"\nstatus open\n\n");
|
134
|
+
g_string_append(out,"\n\\begin_layout Plain Layout\n");
|
135
|
+
|
136
|
+
} else {
|
137
|
+
g_string_append(out, "\n\\begin_layout BeginFrame\n");
|
138
|
+
}
|
139
|
+
break;
|
140
|
+
case 4:
|
141
|
+
g_string_append(out,"\n\\begin_layout Standard");
|
142
|
+
g_string_append(out, "\n\\begin_inset Flex ArticleMode");
|
143
|
+
g_string_append(out, "\nstatus open\n\n");
|
144
|
+
g_string_append(out,"\n\\begin_layout Plain Layout\n");
|
145
|
+
break;
|
146
|
+
default:
|
147
|
+
g_string_append(out,"\n\\begin_layout Standard");
|
148
|
+
g_string_append(out, "\n\\emph on\n");
|
149
|
+
break;
|
150
|
+
}
|
151
|
+
/* Don't allow footnotes */
|
152
|
+
scratch->no_lyx_footnote = TRUE;
|
153
|
+
if (n->children->key == AUTOLABEL) {
|
154
|
+
/* use label for header since one was specified (MMD)*/
|
155
|
+
temp = label_from_string(n->children->str);
|
156
|
+
prefixed_label = prefix_label(heading_name[lev-1]->str,temp,FALSE);
|
157
|
+
print_lyx_node_tree(out, n->children->next, scratch , FALSE);
|
158
|
+
g_string_append(out,"\n\\begin_inset CommandInset label\n");
|
159
|
+
g_string_append(out,"LatexCommand label\n");
|
160
|
+
g_string_append_printf(out, "name \"%s\"",prefixed_label);
|
161
|
+
g_string_append(out,"\n\\end_inset\n");
|
162
|
+
free(prefixed_label);
|
163
|
+
free(temp);
|
164
|
+
} else {
|
165
|
+
/* generate a label by default for MMD */
|
166
|
+
temp = label_from_node_tree(n->children);
|
167
|
+
prefixed_label = prefix_label(heading_name[lev-1]->str,temp,FALSE);
|
168
|
+
print_lyx_node_tree(out, n->children, scratch, FALSE);
|
169
|
+
g_string_append(out,"\n\\begin_inset CommandInset label\n");
|
170
|
+
g_string_append(out,"LatexCommand label\n");
|
171
|
+
g_string_append_printf(out, "name \"%s\"",prefixed_label);
|
172
|
+
g_string_append(out,"\n\\end_inset\n");
|
173
|
+
free(prefixed_label);
|
174
|
+
free(temp);
|
175
|
+
}
|
176
|
+
scratch->no_lyx_footnote = FALSE;
|
177
|
+
switch(lev){
|
178
|
+
case 1: case 2:
|
179
|
+
g_string_append(out,"\n\\end_layout\n");
|
180
|
+
break;
|
181
|
+
case 3:
|
182
|
+
if (scratch->lyx_fragile){
|
183
|
+
g_string_append(out,"\n\\end_layout");
|
184
|
+
g_string_append(out,"\n\\end_inset");
|
185
|
+
g_string_append(out,"\n\\end_layout\n");
|
186
|
+
} else{
|
187
|
+
g_string_append(out, "\n\\end_layout\n");
|
188
|
+
}
|
189
|
+
break;
|
190
|
+
case 4:
|
191
|
+
g_string_append(out,"\n\\end_layout");
|
192
|
+
g_string_append(out,"\n\\end_inset");
|
193
|
+
g_string_append(out,"\n\\end_layout");
|
194
|
+
break;
|
195
|
+
default:
|
196
|
+
g_string_append(out, "\n\\emph default\n");
|
197
|
+
g_string_append(out,"\n\\end_layout");
|
198
|
+
break;
|
199
|
+
}
|
200
|
+
|
201
|
+
break;
|
202
|
+
default:
|
203
|
+
/* most things are not changed for beamer output */
|
204
|
+
print_lyx_node(out, n, scratch,no_newline);
|
205
|
+
}
|
206
|
+
}
|
207
|
+
|
208
|
+
/* print_beamer_endnotes */
|
209
|
+
void print_lyxbeamer_endnotes(GString *out, scratch_pad *scratch) {
|
210
|
+
node *temp_node;
|
211
|
+
scratch->used_notes = reverse_list(scratch->used_notes);
|
212
|
+
node *note = scratch->used_notes;
|
213
|
+
|
214
|
+
// Handle Glossary
|
215
|
+
temp_node = note;
|
216
|
+
while (temp_node != NULL){
|
217
|
+
if(temp_node->key == GLOSSARYSOURCE){
|
218
|
+
g_string_append(out, "\n\\begin_layout BeginFrame\nGlossary\n");
|
219
|
+
g_string_append(out,"\n\\begin_layout Standard");
|
220
|
+
g_string_append(out,"\n\\begin_inset CommandInset nomencl_print");
|
221
|
+
g_string_append(out,"\nLatexCommand printnomenclature");
|
222
|
+
g_string_append(out,"\nset_width \"auto\"\n");
|
223
|
+
g_string_append(out,"\n\\end_inset\n");
|
224
|
+
g_string_append(out,"\n\\end_layout\n");
|
225
|
+
g_string_append(out, "\n\\end_layout\n");
|
226
|
+
g_string_append(out, "\n\\begin_layout EndFrame");
|
227
|
+
g_string_append(out, "\n\\end_layout");
|
228
|
+
break;
|
229
|
+
}
|
230
|
+
temp_node = temp_node->next;
|
231
|
+
}
|
232
|
+
|
233
|
+
if (note == NULL)
|
234
|
+
return;
|
235
|
+
|
236
|
+
note = scratch->used_notes;
|
237
|
+
|
238
|
+
if (tree_contains_key(note,CITATIONSOURCE)){
|
239
|
+
g_string_append(out, "\n\\begin_layout BeginFrame\nReferences\n");
|
240
|
+
g_string_append(out, "\n\\end_layout");
|
241
|
+
}
|
242
|
+
while ( note != NULL) {
|
243
|
+
if (note->key == KEY_COUNTER) {
|
244
|
+
note = note->next;
|
245
|
+
continue;
|
246
|
+
}
|
247
|
+
|
248
|
+
|
249
|
+
if (note->key == CITATIONSOURCE) {
|
250
|
+
g_string_append(out, "\n\\begin_layout Bibliography\n");
|
251
|
+
g_string_append(out,"\\begin_inset CommandInset bibitem\n");
|
252
|
+
g_string_append(out,"LatexCommand bibitem\n");
|
253
|
+
g_string_append_printf(out, "key \"%s\"\n", note->str);
|
254
|
+
g_string_append_printf(out, "label \"%s\"\n", note->str);
|
255
|
+
g_string_append(out,"\n\\end_inset\n");
|
256
|
+
print_lyx_node(out, note, scratch, FALSE);
|
257
|
+
g_string_append(out,"\n\\end_layout\n");
|
258
|
+
} else {
|
259
|
+
/* footnotes handled elsewhere */
|
260
|
+
}
|
261
|
+
|
262
|
+
note = note->next;
|
263
|
+
}
|
264
|
+
g_string_append(out, "\n\\begin_layout EndFrame"); // close last frame
|
265
|
+
g_string_append(out, "\n\\end_layout");
|
266
|
+
|
267
|
+
}
|
@@ -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,79 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
memoir.c -- Memoir add-on to LaTeX writer
|
4
|
+
|
5
|
+
(c) 2013 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
|
+
pad(out, 2, scratch);
|
42
|
+
if ((n->children != NULL) && (n->children->key == VERBATIMTYPE)) {
|
43
|
+
trim_trailing_whitespace(n->children->str);
|
44
|
+
if (strlen(n->children->str) > 0) {
|
45
|
+
g_string_append_printf(out, "\\begin{adjustwidth}{2.5em}{2.5em}\n\\begin{lstlisting}[language=%s]\n", n->children->str);
|
46
|
+
print_raw_node(out, n);
|
47
|
+
g_string_append_printf(out, "\n\\end{lstlisting}\n\\end{adjustwidth}");
|
48
|
+
scratch->padded = 0;
|
49
|
+
break;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
g_string_append_printf(out, "\\begin{adjustwidth}{2.5em}{2.5em}\n\\begin{verbatim}\n\n");
|
53
|
+
print_raw_node(out, n);
|
54
|
+
g_string_append_printf(out, "\n\\end{verbatim}\n\\end{adjustwidth}");
|
55
|
+
scratch->padded = 0;
|
56
|
+
break;
|
57
|
+
case HEADINGSECTION:
|
58
|
+
print_memoir_node_tree(out, n->children, scratch);
|
59
|
+
break;
|
60
|
+
case DEFLIST:
|
61
|
+
pad(out, 2, scratch);
|
62
|
+
g_string_append_printf(out, "\\begin{description}");
|
63
|
+
scratch->padded = 0;
|
64
|
+
print_memoir_node_tree(out, n->children, scratch);
|
65
|
+
pad(out, 1, scratch);
|
66
|
+
g_string_append_printf(out, "\\end{description}");
|
67
|
+
scratch->padded = 0;
|
68
|
+
break;
|
69
|
+
case DEFINITION:
|
70
|
+
pad(out, 2, scratch);
|
71
|
+
scratch->padded = 2;
|
72
|
+
print_memoir_node_tree(out, n->children, scratch);
|
73
|
+
scratch->padded = 0;
|
74
|
+
break;
|
75
|
+
default:
|
76
|
+
/* most things are not changed for memoir output */
|
77
|
+
print_latex_node(out, n, scratch);
|
78
|
+
}
|
79
|
+
}
|
@@ -0,0 +1,483 @@
|
|
1
|
+
/*
|
2
|
+
|
3
|
+
parser.leg -> parser.c -- Parse (Multi)Markdown plain text for
|
4
|
+
conversion into other formats
|
5
|
+
|
6
|
+
(c) 2013 Fletcher T. Penney (http://fletcherpenney.net/).
|
7
|
+
|
8
|
+
Derived from peg-multimarkdown, which was forked from peg-markdown,
|
9
|
+
which is (c) 2008 John MacFarlane (jgm at berkeley dot edu), and
|
10
|
+
licensed under GNU GPL or MIT.
|
11
|
+
|
12
|
+
This program is free software; you can redistribute it and/or modify
|
13
|
+
it under the terms of the GNU General Public License or the MIT
|
14
|
+
license. See LICENSE for details.
|
15
|
+
|
16
|
+
This program is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU General Public License for more details.
|
20
|
+
*/
|
21
|
+
|
22
|
+
#include <getopt.h>
|
23
|
+
#include <libgen.h>
|
24
|
+
#include "parser.h"
|
25
|
+
#include "transclude.h"
|
26
|
+
|
27
|
+
int main(int argc, char **argv)
|
28
|
+
{
|
29
|
+
int numargs;
|
30
|
+
int c;
|
31
|
+
int i;
|
32
|
+
static int batch_flag = 0;
|
33
|
+
static int complete_flag = 0;
|
34
|
+
static int snippet_flag = 0;
|
35
|
+
static int compatibility_flag = 0;
|
36
|
+
static int notes_flag = 0;
|
37
|
+
static int no_notes_flag = 0;
|
38
|
+
static int typography_flag = 0;
|
39
|
+
static int no_typography_flag = 0;
|
40
|
+
static int label_flag = 0;
|
41
|
+
static int no_label_flag = 0;
|
42
|
+
static int obfuscate_flag = 0;
|
43
|
+
static int no_obfuscate_flag = 0;
|
44
|
+
static int process_html_flag = 0;
|
45
|
+
static int random_footnotes_flag = 0;
|
46
|
+
bool list_meta_keys = 0;
|
47
|
+
char *target_meta_key = FALSE;
|
48
|
+
|
49
|
+
static struct option long_options[] = {
|
50
|
+
{"batch", no_argument, &batch_flag, 1}, /* process each file separately */
|
51
|
+
{"to", required_argument, 0, 't'}, /* which output format to use */
|
52
|
+
{"full", no_argument, &complete_flag, 1}, /* complete document */
|
53
|
+
{"snippet", no_argument, &snippet_flag, 1}, /* snippet only */
|
54
|
+
{"output", required_argument, 0, 'o'}, /* which output format to use */
|
55
|
+
{"notes", no_argument, ¬es_flag, 1}, /* use footnotes */
|
56
|
+
{"nonotes", no_argument, &no_notes_flag, 1}, /* don't use footnotes */
|
57
|
+
{"smart", no_argument, &typography_flag, 1}, /* use smart typography */
|
58
|
+
{"nosmart", no_argument, &no_typography_flag, 1}, /* don't use smart typography */
|
59
|
+
{"mask", no_argument, &obfuscate_flag, 1}, /* mask email addresses */
|
60
|
+
{"nomask", no_argument, &no_obfuscate_flag, 1}, /* don't mask email addresses */
|
61
|
+
{"labels", no_argument, &label_flag, 1}, /* generate labels */
|
62
|
+
{"nolabels", no_argument, &no_label_flag, 1}, /* don't generate labels */
|
63
|
+
{"compatibility", no_argument, &compatibility_flag, 1}, /* compatibility mode */
|
64
|
+
{"process-html", no_argument, &process_html_flag, 1}, /* process Markdown inside HTML */
|
65
|
+
{"random", no_argument, &random_footnotes_flag, 1}, /* Use random numbers for footnote links */
|
66
|
+
{"accept", no_argument, 0, 'a'}, /* Accept all proposed CriticMarkup changes */
|
67
|
+
{"reject", no_argument, 0, 'r'}, /* Reject all proposed CriticMarkup changes */
|
68
|
+
{"metadata-keys", no_argument, 0, 'm'}, /* List all metadata keys */
|
69
|
+
{"extract", required_argument, 0, 'e'}, /* show value of specified metadata */
|
70
|
+
{"version", no_argument, 0, 'v'}, /* display version information */
|
71
|
+
{"help", no_argument, 0, 'h'}, /* display usage information */
|
72
|
+
{NULL, 0, NULL, 0}
|
73
|
+
};
|
74
|
+
|
75
|
+
GString *inputbuf;
|
76
|
+
FILE *input;
|
77
|
+
FILE *output;
|
78
|
+
int curchar;
|
79
|
+
GString *filename = NULL;
|
80
|
+
|
81
|
+
char *out;
|
82
|
+
|
83
|
+
/* set up my data for the parser */
|
84
|
+
int output_format = 0;
|
85
|
+
unsigned long extensions = 0;
|
86
|
+
extensions = extensions | EXT_SMART | EXT_NOTES | EXT_OBFUSCATE;
|
87
|
+
|
88
|
+
/* process options */
|
89
|
+
while (1) {
|
90
|
+
int option_index = 0;
|
91
|
+
|
92
|
+
c = getopt_long (argc, argv, "vhco:bfst:me:ar", long_options, &option_index);
|
93
|
+
|
94
|
+
if (c == -1)
|
95
|
+
break;
|
96
|
+
|
97
|
+
switch (c) {
|
98
|
+
case 0: /* handle long_options */
|
99
|
+
/* printf ("option %s", long_options[option_index].name);
|
100
|
+
if (optarg)
|
101
|
+
printf (" with arg %s", optarg);
|
102
|
+
printf("\n"); */
|
103
|
+
break;
|
104
|
+
|
105
|
+
case 'b': /* batch */
|
106
|
+
batch_flag = 1;
|
107
|
+
break;
|
108
|
+
|
109
|
+
case 'c': /* compatibility */
|
110
|
+
compatibility_flag = 1;
|
111
|
+
break;
|
112
|
+
|
113
|
+
case 'o': /* output filename */
|
114
|
+
if (optarg)
|
115
|
+
filename = g_string_new(optarg);
|
116
|
+
break;
|
117
|
+
|
118
|
+
case 'v': /* show version */
|
119
|
+
printf("\nMultiMarkdown version %s\n%s\n",MMD_VERSION, MMD_COPYRIGHT);
|
120
|
+
return(EXIT_SUCCESS);
|
121
|
+
|
122
|
+
case 'h': /* show usage */
|
123
|
+
printf("\nMultiMarkdown version %s\n\n",MMD_VERSION);
|
124
|
+
printf(" %s [OPTION...] [FILE...]\n",argv[0]);
|
125
|
+
printf("\n"
|
126
|
+
" Options:\n"
|
127
|
+
" -h, --help Show help\n"
|
128
|
+
" -v, --version Show version information\n"
|
129
|
+
" -o, --output=FILE Send output to FILE\n"
|
130
|
+
" -t, --to=FORMAT Convert to FORMAT\n"
|
131
|
+
" -b, --batch Process each file separately\n"
|
132
|
+
" -c, --compatibility Markdown compatibility mode\n"
|
133
|
+
" -f, --full Force a complete document\n"
|
134
|
+
" -s, --snippet Force a snippet\n"
|
135
|
+
" --process-html Process Markdown inside of raw HTML\n"
|
136
|
+
" -m, --metadata-keys List all metadata keys\n"
|
137
|
+
" -e, --extract Extract specified metadata\n"
|
138
|
+
" --random Use random numbers for footnote anchors\n"
|
139
|
+
"\n"
|
140
|
+
" -a, --accept Accept all CriticMarkup changes\n"
|
141
|
+
" -r, --reject Reject all CriticMarkup changes\n"
|
142
|
+
"\n"
|
143
|
+
" --smart, --nosmart Toggle smart typography\n"
|
144
|
+
" --notes, --nonotes Toggle footnotes\n"
|
145
|
+
" --labels, --nolabels Disable id attributes for headers\n"
|
146
|
+
" --mask, --nomask Mask email addresses in HTML\n"
|
147
|
+
|
148
|
+
"\nAvailable FORMATs: html(default), latex, beamer, memoir, odf, opml, lyx\n\n"
|
149
|
+
"NOTE: The lyx output format was created by Charles R. Cowan, and \n\tis provided as is.\n\n\n"
|
150
|
+
);
|
151
|
+
return(EXIT_SUCCESS);
|
152
|
+
|
153
|
+
case 't': /* output format */
|
154
|
+
if (strcmp(optarg, "text") == 0)
|
155
|
+
output_format = TEXT_FORMAT;
|
156
|
+
else if (strcmp(optarg, "html") == 0)
|
157
|
+
output_format = HTML_FORMAT;
|
158
|
+
else if (strcmp(optarg, "latex") == 0)
|
159
|
+
output_format = LATEX_FORMAT;
|
160
|
+
else if (strcmp(optarg, "memoir") == 0)
|
161
|
+
output_format = MEMOIR_FORMAT;
|
162
|
+
else if (strcmp(optarg, "beamer") == 0)
|
163
|
+
output_format = BEAMER_FORMAT;
|
164
|
+
else if (strcmp(optarg, "opml") == 0)
|
165
|
+
output_format = OPML_FORMAT;
|
166
|
+
else if (strcmp(optarg, "odf") == 0)
|
167
|
+
output_format = ODF_FORMAT;
|
168
|
+
else if (strcmp(optarg, "rtf") == 0)
|
169
|
+
output_format = RTF_FORMAT;
|
170
|
+
else if (strcmp(optarg, "lyx") == 0)
|
171
|
+
output_format = LYX_FORMAT;
|
172
|
+
else {
|
173
|
+
/* no valid format specified */
|
174
|
+
fprintf(stderr, "%s: Unknown output format '%s'\n",argv[0], optarg);
|
175
|
+
exit(EXIT_FAILURE);
|
176
|
+
}
|
177
|
+
break;
|
178
|
+
|
179
|
+
case 'f': /* full doc */
|
180
|
+
extensions = extensions | EXT_COMPLETE;
|
181
|
+
break;
|
182
|
+
|
183
|
+
case 's': /* snippet only */
|
184
|
+
extensions = extensions | EXT_SNIPPET;
|
185
|
+
break;
|
186
|
+
|
187
|
+
case 'm': /* list metadata */
|
188
|
+
list_meta_keys = 1;
|
189
|
+
break;
|
190
|
+
|
191
|
+
case 'e': /* extract metadata */
|
192
|
+
target_meta_key = strdup(optarg);
|
193
|
+
break;
|
194
|
+
|
195
|
+
case '?': /* long handles */
|
196
|
+
break;
|
197
|
+
|
198
|
+
case 'a': /* Accept CriticMarkup changes */
|
199
|
+
extensions = extensions | EXT_CRITIC_ACCEPT;
|
200
|
+
break;
|
201
|
+
|
202
|
+
case 'r': /* Reject CriticMarkup changes */
|
203
|
+
extensions = extensions | EXT_CRITIC_REJECT;
|
204
|
+
break;
|
205
|
+
|
206
|
+
default:
|
207
|
+
fprintf(stderr,"Error parsing options.\n");
|
208
|
+
abort();
|
209
|
+
}
|
210
|
+
}
|
211
|
+
|
212
|
+
/* Compatibility mode emulates the behavior of Markdown.pl */
|
213
|
+
if (compatibility_flag) {
|
214
|
+
extensions = 0x000000;
|
215
|
+
extensions = extensions | EXT_COMPATIBILITY | EXT_NO_LABELS | EXT_OBFUSCATE;
|
216
|
+
}
|
217
|
+
|
218
|
+
/* apply extensions from long options*/
|
219
|
+
if (complete_flag)
|
220
|
+
extensions = extensions | EXT_COMPLETE;
|
221
|
+
|
222
|
+
if (snippet_flag)
|
223
|
+
extensions = extensions | EXT_SNIPPET;
|
224
|
+
|
225
|
+
if (notes_flag)
|
226
|
+
extensions = extensions | EXT_NOTES;
|
227
|
+
|
228
|
+
if (no_notes_flag)
|
229
|
+
extensions &= ~EXT_NOTES;
|
230
|
+
|
231
|
+
if (typography_flag)
|
232
|
+
extensions = extensions | EXT_SMART;
|
233
|
+
|
234
|
+
if (no_typography_flag)
|
235
|
+
extensions &= ~EXT_SMART;
|
236
|
+
|
237
|
+
if (label_flag)
|
238
|
+
extensions &= ~EXT_NO_LABELS;
|
239
|
+
|
240
|
+
if (no_label_flag)
|
241
|
+
extensions = extensions | EXT_NO_LABELS;
|
242
|
+
|
243
|
+
if (obfuscate_flag)
|
244
|
+
extensions = extensions | EXT_OBFUSCATE;
|
245
|
+
|
246
|
+
if (no_obfuscate_flag)
|
247
|
+
extensions &= ~EXT_OBFUSCATE;
|
248
|
+
|
249
|
+
if (process_html_flag)
|
250
|
+
extensions = extensions | EXT_PROCESS_HTML;
|
251
|
+
|
252
|
+
if (random_footnotes_flag)
|
253
|
+
extensions = extensions | EXT_RANDOM_FOOT;
|
254
|
+
|
255
|
+
/* Enable HEADINGSECTION for certain formats */
|
256
|
+
if ((output_format == OPML_FORMAT) || (output_format == BEAMER_FORMAT) || (output_format == LYX_FORMAT))
|
257
|
+
extensions = extensions | EXT_HEADINGSECTION;
|
258
|
+
|
259
|
+
/* fix numbering to account for options */
|
260
|
+
argc -= optind;
|
261
|
+
argv += optind;
|
262
|
+
|
263
|
+
/* We expect argc and argv to still point just one below the start of remaining args */
|
264
|
+
argc++;
|
265
|
+
argv--;
|
266
|
+
|
267
|
+
/* any filenames */
|
268
|
+
numargs = argc -1;
|
269
|
+
|
270
|
+
if (batch_flag && (numargs != 0)) {
|
271
|
+
/* we have multiple file names -- handle individually */
|
272
|
+
|
273
|
+
for (i = 0; i < numargs; i++) {
|
274
|
+
inputbuf = g_string_new("");
|
275
|
+
char *temp = NULL;
|
276
|
+
char *folder = NULL;
|
277
|
+
|
278
|
+
/* Read file */
|
279
|
+
if ((input = fopen(argv[i+1], "r")) == NULL ) {
|
280
|
+
perror(argv[i+1]);
|
281
|
+
g_string_free(inputbuf, true);
|
282
|
+
g_string_free(filename, true);
|
283
|
+
exit(EXIT_FAILURE);
|
284
|
+
}
|
285
|
+
|
286
|
+
while ((curchar = fgetc(input)) != EOF)
|
287
|
+
g_string_append_c(inputbuf, curchar);
|
288
|
+
fclose(input);
|
289
|
+
|
290
|
+
/* list metadata keys */
|
291
|
+
if (list_meta_keys) {
|
292
|
+
out = extract_metadata_keys(inputbuf->str, extensions);
|
293
|
+
if (out != NULL) {
|
294
|
+
fprintf(stdout, "%s", out);
|
295
|
+
free(out);
|
296
|
+
g_string_free(inputbuf, true);
|
297
|
+
free(target_meta_key);
|
298
|
+
return(EXIT_SUCCESS);
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
/* extract metadata */
|
303
|
+
if (target_meta_key) {
|
304
|
+
out = extract_metadata_value(inputbuf->str, extensions, target_meta_key);
|
305
|
+
if (out != NULL)
|
306
|
+
fprintf(stdout, "%s\n", out);
|
307
|
+
free(out);
|
308
|
+
g_string_free(inputbuf, true);
|
309
|
+
free(target_meta_key);
|
310
|
+
return(EXIT_SUCCESS);
|
311
|
+
}
|
312
|
+
|
313
|
+
if (!(extensions & EXT_COMPATIBILITY)) {
|
314
|
+
temp = strdup(argv[i+1]);
|
315
|
+
folder = dirname(temp);
|
316
|
+
transclude_source(inputbuf, folder, NULL, output_format);
|
317
|
+
free(temp);
|
318
|
+
// free(folder);
|
319
|
+
}
|
320
|
+
|
321
|
+
target_meta_key = extract_metadata_value(inputbuf->str, extensions, "latexmode");
|
322
|
+
if (target_meta_key != NULL) {
|
323
|
+
temp = label_from_string(target_meta_key);
|
324
|
+
if (strcmp(temp, "beamer") == 0) {
|
325
|
+
extensions = extensions | EXT_HEADINGSECTION;
|
326
|
+
}
|
327
|
+
free(temp);
|
328
|
+
}
|
329
|
+
free(target_meta_key);
|
330
|
+
|
331
|
+
out = markdown_to_string(inputbuf->str, extensions, output_format);
|
332
|
+
|
333
|
+
g_string_free(inputbuf, true);
|
334
|
+
|
335
|
+
/* set up for output */
|
336
|
+
temp = argv[i+1]; /* get current filename */
|
337
|
+
if (strrchr(temp,'.') != NULL) {
|
338
|
+
long count = strrchr(temp,'.') - temp;
|
339
|
+
if (count != 0) {
|
340
|
+
/* truncate string at "." */
|
341
|
+
temp[count] = '\0';
|
342
|
+
}
|
343
|
+
}
|
344
|
+
|
345
|
+
filename = g_string_new(temp);
|
346
|
+
|
347
|
+
if (output_format == TEXT_FORMAT) {
|
348
|
+
g_string_append(filename,".txt");
|
349
|
+
} else if (output_format == HTML_FORMAT) {
|
350
|
+
g_string_append(filename,".html");
|
351
|
+
} else if (output_format == LATEX_FORMAT) {
|
352
|
+
g_string_append(filename,".tex");
|
353
|
+
} else if (output_format == BEAMER_FORMAT) {
|
354
|
+
g_string_append(filename,".tex");
|
355
|
+
} else if (output_format == MEMOIR_FORMAT) {
|
356
|
+
g_string_append(filename,".tex");
|
357
|
+
} else if (output_format == ODF_FORMAT) {
|
358
|
+
g_string_append(filename,".fodt");
|
359
|
+
} else if (output_format == OPML_FORMAT) {
|
360
|
+
g_string_append(filename,".opml");
|
361
|
+
} else if (output_format == LYX_FORMAT) {
|
362
|
+
g_string_append(filename,".lyx");
|
363
|
+
} else if (output_format == RTF_FORMAT) {
|
364
|
+
g_string_append(filename,".rtf");
|
365
|
+
} else {
|
366
|
+
/* default extension -- in this case we only have 1 */
|
367
|
+
g_string_append(filename,".txt");
|
368
|
+
}
|
369
|
+
|
370
|
+
if (!(output = fopen(filename->str, "w"))) {
|
371
|
+
perror(filename->str);
|
372
|
+
} else {
|
373
|
+
fprintf(output, "%s\n",out);
|
374
|
+
fclose(output);
|
375
|
+
}
|
376
|
+
|
377
|
+
g_string_free(filename,true);
|
378
|
+
|
379
|
+
if (out != NULL)
|
380
|
+
free(out);
|
381
|
+
}
|
382
|
+
} else {
|
383
|
+
/* get input from stdin or concat all files */
|
384
|
+
inputbuf = g_string_new("");
|
385
|
+
char *folder = NULL;
|
386
|
+
char *temp = NULL;
|
387
|
+
|
388
|
+
folder = getcwd(0,0);
|
389
|
+
|
390
|
+
if (numargs == 0) {
|
391
|
+
/* get stdin */
|
392
|
+
while ((curchar = fgetc(stdin)) != EOF)
|
393
|
+
g_string_append_c(inputbuf, curchar);
|
394
|
+
fclose(stdin);
|
395
|
+
} else {
|
396
|
+
/* get files */
|
397
|
+
free(folder);
|
398
|
+
temp = strdup(argv[1]);
|
399
|
+
folder = dirname(temp);
|
400
|
+
|
401
|
+
for (i = 0; i < numargs; i++) {
|
402
|
+
if ((input = fopen(argv[i+1], "r")) == NULL ) {
|
403
|
+
perror(argv[i+1]);
|
404
|
+
g_string_free(inputbuf, true);
|
405
|
+
g_string_free(filename, true);
|
406
|
+
free(folder);
|
407
|
+
free(temp);
|
408
|
+
exit(EXIT_FAILURE);
|
409
|
+
}
|
410
|
+
|
411
|
+
while ((curchar = fgetc(input)) != EOF)
|
412
|
+
g_string_append_c(inputbuf, curchar);
|
413
|
+
fclose(input);
|
414
|
+
}
|
415
|
+
}
|
416
|
+
|
417
|
+
if (!(extensions & EXT_COMPATIBILITY))
|
418
|
+
transclude_source(inputbuf, folder, NULL, output_format);
|
419
|
+
|
420
|
+
free(temp);
|
421
|
+
|
422
|
+
//if (folder != NULL)
|
423
|
+
// free(folder);
|
424
|
+
|
425
|
+
/* list metadata keys */
|
426
|
+
if (list_meta_keys) {
|
427
|
+
out = extract_metadata_keys(inputbuf->str, extensions);
|
428
|
+
if (out != NULL) {
|
429
|
+
fprintf(stdout, "%s", out);
|
430
|
+
free(out);
|
431
|
+
g_string_free(inputbuf, true);
|
432
|
+
free(target_meta_key);
|
433
|
+
return(EXIT_SUCCESS);
|
434
|
+
}
|
435
|
+
}
|
436
|
+
|
437
|
+
/* extract metadata */
|
438
|
+
if (target_meta_key) {
|
439
|
+
out = extract_metadata_value(inputbuf->str, extensions, target_meta_key);
|
440
|
+
if (out != NULL)
|
441
|
+
fprintf(stdout, "%s\n", out);
|
442
|
+
free(out);
|
443
|
+
g_string_free(inputbuf, true);
|
444
|
+
free(target_meta_key);
|
445
|
+
return(EXIT_SUCCESS);
|
446
|
+
}
|
447
|
+
|
448
|
+
target_meta_key = extract_metadata_value(inputbuf->str, extensions, "latexmode");
|
449
|
+
if (target_meta_key != NULL) {
|
450
|
+
temp = label_from_string(target_meta_key);
|
451
|
+
if (strcmp(temp, "beamer") == 0) {
|
452
|
+
extensions = extensions | EXT_HEADINGSECTION;
|
453
|
+
}
|
454
|
+
free(temp);
|
455
|
+
}
|
456
|
+
free(target_meta_key);
|
457
|
+
|
458
|
+
out = markdown_to_string(inputbuf->str, extensions, output_format);
|
459
|
+
|
460
|
+
g_string_free(inputbuf, true);
|
461
|
+
|
462
|
+
/* did we specify an output filename; "-" equals stdout */
|
463
|
+
if ((filename == NULL) || (strcmp(filename->str, "-") == 0)) {
|
464
|
+
output = stdout;
|
465
|
+
} else if (!(output = fopen(filename->str, "w"))) {
|
466
|
+
perror(filename->str);
|
467
|
+
if (out != NULL)
|
468
|
+
free(out);
|
469
|
+
g_string_free(filename, true);
|
470
|
+
return 1;
|
471
|
+
}
|
472
|
+
|
473
|
+
fprintf(output, "%s\n",out);
|
474
|
+
fclose(output);
|
475
|
+
|
476
|
+
g_string_free(filename, true);
|
477
|
+
|
478
|
+
if (out != NULL)
|
479
|
+
free(out);
|
480
|
+
}
|
481
|
+
|
482
|
+
return(EXIT_SUCCESS);
|
483
|
+
}
|