rmultimarkdown 4.6.0.2 → 4.7.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -14,10 +14,10 @@
14
14
 
15
15
  #define TABSTOP 4
16
16
 
17
- #define MMD_VERSION "4.6"
17
+ #define MMD_VERSION "4.7"
18
18
 
19
19
  #define MMD_COPYRIGHT \
20
- "Copyright (c) 2013-2014 Fletcher T. Penney.\n\n" \
20
+ "Copyright (c) 2013-2015 Fletcher T. Penney.\n\n" \
21
21
  "LyX export code (c) 2013-2014 Charles R. Cowan,\n" \
22
22
  "licensed under both GPL and MIT licenses.\n\n" \
23
23
  "portions based on peg-markdown - Copyright (c) 2008-2009 John MacFarlane.\n" \
@@ -71,6 +71,7 @@ typedef struct {
71
71
  int odf_para_type; /* what type of paragraph do we need? */
72
72
  bool odf_list_needs_end_p; /* is there a <p> that need to be closed */
73
73
  int random_seed_base; /* Allow random footnotes */
74
+ int toc_level; /* Track depth for TOC */
74
75
  int table_row; /* CRC - Track the current row number */
75
76
  int lyx_para_type; /* CRC - the type of paragraph being processed */
76
77
  int lyx_level; /* CRC - nesting level */
@@ -180,5 +181,6 @@ int tree_contains_key_count(node *list, int key);
180
181
  bool check_timeout();
181
182
 
182
183
  void debug_node(node *n);
184
+ void debug_node_tree(node *n);
183
185
 
184
186
  #endif
@@ -474,6 +474,20 @@ void print_rtf_node(GString *out, node *n, scratch_pad *scratch) {
474
474
  free(temp);
475
475
  }
476
476
  break;
477
+ case HTMLBLOCK:
478
+ /* don't print HTML block */
479
+ /* but do print HTML comments for raw RTF */
480
+ if (strncmp(n->str,"<!--",4) == 0) {
481
+ pad(out, 2, scratch);
482
+ /* trim "-->" from end */
483
+ n->str[strlen(n->str)-3] = '\0';
484
+ g_string_append_printf(out, "%s", &n->str[4]);
485
+ scratch->padded = 0;
486
+ }
487
+ break;
488
+ case TOC:
489
+ print_rtf_node_tree(out,n->children, scratch);
490
+ break;
477
491
  default:
478
492
  fprintf(stderr, "print_rtf_node encountered unknown node key = %d\n",n->key);
479
493
  g_string_append_printf(out, "%s",n->str);
@@ -3,7 +3,7 @@
3
3
  test.c -- plain text writer function as an example.
4
4
  Recreates the input source.
5
5
 
6
- (c) 2013 Fletcher T. Penney (http://fletcherpenney.net/).
6
+ (c) 2013-2015 Fletcher T. Penney (http://fletcherpenney.net/).
7
7
 
8
8
  This program is free software; you can redistribute it and/or modify
9
9
  it under the terms of the GNU General Public License or the MIT
@@ -0,0 +1,142 @@
1
+ /*
2
+
3
+ toc.c -- Table of contents
4
+
5
+ (c) 2013-2015 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 "toc.h"
19
+
20
+
21
+ /* print_toc_node_tree -- convert node tree to LaTeX */
22
+ void print_toc_node_tree(GString *out, node *list, scratch_pad *scratch) {
23
+ #ifdef DEBUG_ON
24
+ fprintf(stderr, "print_toc_node_tree\n");
25
+ #endif
26
+ int lev;
27
+ while (list != NULL) {
28
+ if (list->key == HEADINGSECTION) {
29
+ lev = list->children->key;
30
+
31
+ print_toc_section_and_children(out, list, scratch);
32
+
33
+ while ((list->next != NULL) && (list->next->key == HEADINGSECTION)
34
+ && (list->next->children->key > lev)) {
35
+ list = list->next;
36
+ }
37
+ } else {
38
+ print_toc_node(out, list, scratch);
39
+ }
40
+ list = list->next;
41
+ }
42
+ }
43
+
44
+ /* print_toc_section_and_children -- we want to stay inside the outline structure */
45
+ void print_toc_section_and_children(GString *out, node *list, scratch_pad *scratch) {
46
+ #ifdef DEBUG_ON
47
+ fprintf(stderr, "print_toc_section_and_children: %d\n",list->key);
48
+ #endif
49
+ int lev = list->children->key;
50
+
51
+ /* print current section (parent) */
52
+ print_toc_node(out, list, scratch);
53
+
54
+ scratch->toc_level ++;
55
+
56
+ /* check for child nodes */
57
+ while ((list->next != NULL) && (list->next->key == HEADINGSECTION) && (list->next->children->key > lev)) {
58
+ /* next item is also a HEADINGSECTION and is a child */
59
+ if (list->next->children->key - lev == 1)
60
+ print_toc_section_and_children(out, list->next, scratch);
61
+ list = list->next;
62
+ }
63
+
64
+ scratch->toc_level --;
65
+ }
66
+
67
+ /* print_toc_node -- convert given node to OPML and append */
68
+ void print_toc_node(GString *out, node *n, scratch_pad *scratch) {
69
+ char *temp;
70
+ int i;
71
+
72
+ #ifdef DEBUG_ON
73
+ fprintf(stderr, "print_toc_node: %d\n",n->key);
74
+ #endif
75
+ switch (n->key) {
76
+ case HEADINGSECTION:
77
+ /* Need to handle "nesting" properly */
78
+ for (i = 0; i < scratch->toc_level; ++i)
79
+ {
80
+ g_string_append_printf(out, "\t");
81
+ }
82
+ g_string_append_printf(out, "* ");
83
+
84
+ /* Print header */
85
+ print_toc_node(out, n->children, scratch);
86
+
87
+ break;
88
+ case H1: case H2: case H3: case H4: case H5: case H6:
89
+ if ((n->children != NULL) && (n->children->key == AUTOLABEL)) {
90
+ temp = label_from_string(n->children->str);
91
+ /* use label for header since one was specified (MMD)*/
92
+ g_string_append_printf(out, "[");
93
+ print_toc_node_tree(out, n->children, scratch);
94
+ g_string_append_printf(out, "][%s]\n", temp);
95
+ } else {
96
+ temp = label_from_node_tree(n->children);
97
+ g_string_append_printf(out, "[");
98
+ print_toc_node_tree(out, n->children, scratch);
99
+ g_string_append_printf(out, "][%s]\n", temp);
100
+ }
101
+ free(temp);
102
+ break;
103
+ case STR:
104
+ print_toc_string(out, n->str);
105
+ break;
106
+ case SPACE:
107
+ g_string_append_printf(out, "%s", n->str);
108
+ break;
109
+ case LINK:
110
+ print_toc_node_tree(out, n->children, scratch);
111
+ break;
112
+ case LINKREFERENCE:
113
+ break;
114
+ case AUTOLABEL:
115
+ break;
116
+ case LIST:
117
+ print_toc_node_tree(out, n->children, scratch);
118
+ break;
119
+ default: fprintf(stderr, "print_html_node encountered unknown node key = %d\n",n->key);
120
+ break;
121
+ }
122
+ #ifdef DEBUG_ON
123
+ fprintf(stderr, "finish print_toc_node: %d\n", n->key);
124
+ #endif
125
+ }
126
+
127
+ /* print_toc_string - print string, escaping for OPML */
128
+ void print_toc_string(GString *out, char *str) {
129
+ while (*str != '\0') {
130
+ switch (*str) {
131
+ case '[':
132
+ g_string_append_printf(out, "\\[");
133
+ break;
134
+ case ']':
135
+ g_string_append_printf(out, "\\]");
136
+ break;
137
+ default:
138
+ g_string_append_c(out, *str);
139
+ }
140
+ str++;
141
+ }
142
+ }
@@ -0,0 +1,15 @@
1
+ #ifndef TOC_PARSER_H
2
+ #define TOC_PARSER_H
3
+
4
+ #include "parser.h"
5
+ #include "writer.h"
6
+
7
+ void begin_toc_output(GString *out, node* list, scratch_pad *scratch);
8
+ void print_toc_node_tree(GString *out, node *list, scratch_pad *scratch);
9
+ void print_toc_node(GString *out, node *n, scratch_pad *scratch);
10
+ void print_toc_section_and_children(GString *out, node *list, scratch_pad *scratch);
11
+ void end_toc_output(GString *out, node* list, scratch_pad *scratch);
12
+ void print_toc_string(GString *out, char *str);
13
+
14
+
15
+ #endif
@@ -17,6 +17,9 @@
17
17
 
18
18
  #include "transclude.h"
19
19
  #include "parser.h"
20
+ #if defined(__WIN32)
21
+ #include <windows.h>
22
+ #endif
20
23
 
21
24
 
22
25
  /* Combine directory and filename to create a full path */
@@ -48,19 +51,43 @@ char * path_from_dir_base(char *dir, char *base) {
48
51
  return result;
49
52
  }
50
53
 
54
+ /* Separate filename and directory from a full path */
55
+ /* See http://stackoverflow.com/questions/1575278/function-to-split-a-filepath-into-path-and-file */
56
+ void split_path_file(char** dir, char** file, char *path) {
57
+ char *slash = path, *next;
58
+ #if defined(__WIN32)
59
+ const char sep[] = "\\";
60
+ #else
61
+ const char sep[] = "/";
62
+ #endif
63
+
64
+ while ((next = strpbrk(slash + 1, sep))) slash = next;
65
+ if (path != slash) slash++;
66
+ *dir = strndup(path, slash - path);
67
+ *file = strdup(slash);
68
+ }
69
+
51
70
  /* Return pointer to beginning of text without metadata */
71
+ /* NOTE: This is not a new string, and does not need to be freed separately */
52
72
  char * source_without_metadata(char * source, unsigned long extensions ) {
53
73
  char *result;
54
74
 
55
75
  if (has_metadata(source, extensions)) {
56
76
  /* If we have metadata, then return just the body */
77
+ /* TODO: This could miss YAML Metadata that does not contain
78
+ blank line afterwards */
57
79
  result = strstr(source, "\n\n");
58
80
 
59
81
  if (result != NULL)
60
- return result+2;
82
+ return result + 2;
61
83
  }
62
84
 
63
85
  /* No metadata, so return original pointer */
86
+
87
+ /* But check for UTF-8 BOM and skip if present */
88
+ if (strncmp(source, "\xef\xbb\xbf",3) == 0)
89
+ return source + 3;
90
+
64
91
  return source;
65
92
  }
66
93
 
@@ -70,7 +97,7 @@ char * source_without_metadata(char * source, unsigned long extensions ) {
70
97
  Pass the path to the current folder if available -- should be a full path.
71
98
 
72
99
  Keep track of what we're parsing to prevent recursion using stack. */
73
- void transclude_source(GString *source, char *basedir, char *stack, int output_format) {
100
+ void transclude_source(GString *source, char *basedir, char *stack, int output_format, GString *manifest) {
74
101
  char *base = NULL;
75
102
  char *path = NULL;
76
103
  char *start;
@@ -165,6 +192,18 @@ void transclude_source(GString *source, char *basedir, char *stack, int output_f
165
192
 
166
193
  pos = stop - source->str;
167
194
 
195
+ /* Add to the manifest (if not already included) */
196
+ if (manifest != NULL) {
197
+ temp = strstr(manifest->str,filename->str);
198
+
199
+ if ((temp != NULL) && (temp[strlen(filename->str)] == '\n')){
200
+ /* Already on manifest */
201
+ } else {
202
+ g_string_append_printf(manifest,"%s\n",filename->str);
203
+ }
204
+ }
205
+
206
+
168
207
  /* Don't reparse ourselves */
169
208
  if (stack != NULL) {
170
209
  temp = strstr(stack,filename->str);
@@ -177,7 +216,15 @@ void transclude_source(GString *source, char *basedir, char *stack, int output_f
177
216
  }
178
217
 
179
218
  /* Read file */
219
+ #if defined(__WIN32)
220
+ int wchars_num = MultiByteToWideChar(CP_UTF8, 0, filename->str, -1, NULL, 0);
221
+ wchar_t wstr[wchars_num];
222
+ MultiByteToWideChar(CP_UTF8, 0, filename->str, -1, wstr, wchars_num);
223
+
224
+ if ((input = _wfopen(wstr, L"r")) != NULL ) {
225
+ #else
180
226
  if ((input = fopen(filename->str, "r")) != NULL ) {
227
+ #endif
181
228
  filebuffer = g_string_new("");
182
229
 
183
230
  while ((curchar = fgetc(input)) != EOF)
@@ -195,8 +242,18 @@ void transclude_source(GString *source, char *basedir, char *stack, int output_f
195
242
 
196
243
 
197
244
  /* Recursively transclude files */
198
- transclude_source(filebuffer, folder->str, stackstring->str, output_format);
199
245
 
246
+ /* We want to reset the base directory if we enter a subdirectory */
247
+ char * new_dir;
248
+ char * file_only;
249
+ split_path_file(&new_dir, &file_only, filename->str);
250
+
251
+ /* transclude_source(filebuffer, folder->str, stackstring->str, output_format, manifest); */
252
+ transclude_source(filebuffer, new_dir, stackstring->str, output_format, manifest);
253
+
254
+ free(new_dir);
255
+ free(file_only);
256
+
200
257
  temp = source_without_metadata(filebuffer->str, 0x000000);
201
258
 
202
259
  g_string_insert(source, pos, temp);
@@ -224,11 +281,27 @@ void transclude_source(GString *source, char *basedir, char *stack, int output_f
224
281
  /* Allow for a footer to specify files to be appended to the end of the text, and then transcluded.
225
282
  Useful for appending a list of footnotes, citations, abbreviations, etc. to each separate file,
226
283
  but not including multiple copies when processing the master file. */
227
- void append_mmd_footers(GString *source) {
284
+ void append_mmd_footer(GString *source) {
228
285
  /* Look for mmd_footer metadata */
229
286
  if (has_metadata(source->str, 0x000000)) {
230
287
  char *meta = extract_metadata_value(source->str, 0x000000, "mmdfooter");
231
288
  if (meta != NULL)
232
- g_string_append_printf(source, "\n\n{{%s}}\n",meta);
289
+ g_string_append_printf(source, "\n\n{{%s}}\n", meta);
290
+ }
291
+ }
292
+
293
+ void prepend_mmd_header(GString *source) {
294
+ /* Same thing, but to be inserted after metadata and before content */
295
+ if (has_metadata(source->str, 0x000000)) {
296
+ char *meta = extract_metadata_value(source->str, 0x000000, "mmdheader");
297
+ if (meta != NULL) {
298
+ char *content = strstr(source->str, "\n\n");
299
+ if (content != NULL) {
300
+ size_t pos = content - source->str;
301
+ g_string_insert_printf(source, pos, "\n\n{{%s}}", meta);
302
+ } else {
303
+ g_string_append_printf(source, "\n\n{{%s}}\n", meta);
304
+ }
305
+ }
233
306
  }
234
307
  }
@@ -23,5 +23,6 @@
23
23
  #include "GLibFacade.h"
24
24
 
25
25
  char * source_without_metadata(char * source, unsigned long extensions);
26
- void transclude_source(GString *source, char *basedir, char *stack, int format);
27
- void append_mmd_footers(GString *source);
26
+ void transclude_source(GString *source, char *basedir, char *stack, int format, GString *manifest);
27
+ void append_mmd_footer(GString *source);
28
+ void prepend_mmd_header(GString *source);
@@ -3,7 +3,7 @@
3
3
  writer.c -- General routines for converting parse structure to various
4
4
  output formats.
5
5
 
6
- (c) 2013 Fletcher T. Penney (http://fletcherpenney.net/).
6
+ (c) 2013-2015 Fletcher T. Penney (http://fletcherpenney.net/).
7
7
 
8
8
  Derived from peg-multimarkdown, which was forked from peg-markdown,
9
9
  which is (c) 2008 John MacFarlane (jgm at berkeley dot edu), and
@@ -41,13 +41,13 @@ char * export_node_tree(node *list, int format, unsigned long extensions) {
41
41
  (format != CRITIC_ACCEPT_FORMAT) &&
42
42
  (format != CRITIC_REJECT_FORMAT) &&
43
43
  (format != CRITIC_HTML_HIGHLIGHT_FORMAT)) {
44
- /* Parse for link, images, etc reference definitions */
45
- extract_references(list, scratch);
46
-
47
44
  /* Find defined abbreviations */
48
45
  extract_abbreviations(list, scratch);
49
46
  /* Apply those abbreviations to source text */
50
47
  find_abbreviations(list, scratch);
48
+
49
+ /* Parse for link, images, etc reference definitions */
50
+ extract_references(list, scratch);
51
51
  }
52
52
 
53
53
  /* Change our desired format based on metadata */
@@ -138,6 +138,10 @@ char * export_node_tree(node *list, int format, unsigned long extensions) {
138
138
  case CRITIC_HTML_HIGHLIGHT_FORMAT:
139
139
  print_critic_html_highlight_node_tree(out, list, scratch);
140
140
  break;
141
+ case TOC_FORMAT:
142
+ scratch->toc_level = 0;
143
+ print_toc_node_tree(out,list,scratch);
144
+ break;
141
145
  default:
142
146
  fprintf(stderr, "Unknown export format = %d\n",format);
143
147
  exit(EXIT_FAILURE);
@@ -225,6 +229,8 @@ void extract_abbreviations(node *list, scratch_pad *scratch) {
225
229
  case HEADINGSECTION:
226
230
  case RAW:
227
231
  case LIST:
232
+ case BLOCKQUOTEMARKER:
233
+ case BLOCKQUOTE:
228
234
  extract_abbreviations(list->children, scratch);
229
235
  break;
230
236
  default:
@@ -293,11 +299,19 @@ void find_abbreviations(node *list, scratch_pad *scratch) {
293
299
  }
294
300
  break;
295
301
  case LIST:
302
+ case ORDEREDLIST:
303
+ case BULLETLIST:
304
+ case LISTITEM:
296
305
  case HEADINGSECTION:
297
306
  case PARA:
307
+ case PLAIN:
298
308
  case LINK:
299
309
  case LINKREFERENCE:
300
310
  case NOTEREFERENCE:
311
+ case NOTESOURCE:
312
+ case GLOSSARYSOURCE:
313
+ case BLOCKQUOTEMARKER:
314
+ case BLOCKQUOTE:
301
315
  /* Check children of these elements */
302
316
  find_abbreviations(list->children, scratch);
303
317
  break;
@@ -714,4 +728,4 @@ link_data * load_link_data(node *n, scratch_pad *scratch) {
714
728
  }
715
729
 
716
730
  return r;
717
- }
731
+ }
@@ -11,6 +11,7 @@
11
11
  #include "odf.h"
12
12
  #include "rtf.h"
13
13
  #include "critic.h"
14
+ #include "toc.h"
14
15
 
15
16
  char * export_node_tree(node *list, int format, unsigned long extensions);
16
17