rmultimarkdown 6.2.2.1 → 6.4.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/ext/Makefile +2 -2
  3. data/ext/mmd/aho-corasick.c +12 -8
  4. data/ext/mmd/beamer.c +29 -0
  5. data/ext/mmd/critic_markup.c +100 -4
  6. data/ext/mmd/critic_markup.h +7 -0
  7. data/ext/mmd/d_string.c +502 -119
  8. data/ext/mmd/epub.c +2 -4
  9. data/ext/mmd/file.c +436 -0
  10. data/ext/mmd/file.h +153 -0
  11. data/ext/mmd/html.c +130 -37
  12. data/ext/mmd/include/d_string.h +20 -19
  13. data/ext/mmd/include/libMultiMarkdown.h +42 -27
  14. data/ext/mmd/include/token.h +15 -15
  15. data/ext/mmd/latex.c +107 -30
  16. data/ext/mmd/lexer.c +19 -7
  17. data/ext/mmd/lexer.h +2 -2
  18. data/ext/mmd/memoir.c +29 -0
  19. data/ext/mmd/mmd.c +65 -39
  20. data/ext/mmd/object_pool.h +4 -4
  21. data/ext/mmd/opendocument-content.c +95 -13
  22. data/ext/mmd/opendocument.c +315 -313
  23. data/ext/mmd/opml-lexer.c +2183 -0
  24. data/ext/mmd/opml-lexer.h +157 -0
  25. data/ext/mmd/opml-parser.c +1193 -0
  26. data/ext/mmd/opml-parser.h +15 -0
  27. data/ext/mmd/opml-reader.c +435 -0
  28. data/ext/mmd/opml-reader.h +111 -0
  29. data/ext/mmd/opml.c +511 -0
  30. data/ext/mmd/opml.h +115 -0
  31. data/ext/mmd/parser.c +2 -0
  32. data/ext/mmd/rng.c +1 -1
  33. data/ext/mmd/scanners.c +51663 -24824
  34. data/ext/mmd/stack.c +4 -2
  35. data/ext/mmd/stack.h +8 -8
  36. data/ext/mmd/textbundle.c +2 -4
  37. data/ext/mmd/token.c +24 -12
  38. data/ext/mmd/token_pairs.c +2 -2
  39. data/ext/mmd/token_pairs.h +10 -10
  40. data/ext/mmd/transclude.c +1 -226
  41. data/ext/mmd/transclude.h +0 -8
  42. data/ext/mmd/uuid.c +3 -3
  43. data/ext/mmd/version.h +3 -3
  44. data/ext/mmd/writer.c +99 -30
  45. data/ext/mmd/writer.h +11 -0
  46. data/lib/multi_markdown.bundle +0 -0
  47. data/lib/multi_markdown/version.rb +1 -1
  48. metadata +13 -5
  49. data/ext/mmd/fodt.c +0 -2288
  50. data/ext/mmd/fodt.h +0 -81
@@ -87,8 +87,10 @@ stack * stack_new(int startingSize) {
87
87
 
88
88
  /// Free the stack
89
89
  void stack_free(stack * s) {
90
- free(s->element);
91
- free(s);
90
+ if (s) {
91
+ free(s->element);
92
+ free(s);
93
+ }
92
94
  }
93
95
 
94
96
 
@@ -71,39 +71,39 @@ typedef struct stack stack;
71
71
  /// Create a new stack with dynamic storage with an
72
72
  /// initial capacity (0 to use default capacity)
73
73
  stack * stack_new(
74
- int startingSize //!< Default capacity for stack
74
+ int startingSize //!< Default capacity for stack
75
75
  );
76
76
 
77
77
 
78
78
  /// Free the stack
79
79
  void stack_free(
80
- stack * s //!< Stack to be freed
80
+ stack * s //!< Stack to be freed
81
81
  );
82
82
 
83
83
 
84
84
  /// Add a new pointer to the stack
85
85
  void stack_push(
86
- stack * s, //!< Stack to use
87
- void * element //!< Pointer to push onto stack
86
+ stack * s, //!< Stack to use
87
+ void * element //!< Pointer to push onto stack
88
88
  );
89
89
 
90
90
 
91
91
  /// Pop the top pointer off the stack and return it
92
92
  void * stack_pop(
93
- stack * s //!< Stack to examine
93
+ stack * s //!< Stack to examine
94
94
  );
95
95
 
96
96
 
97
97
  /// Peek at the top pointer on the stack (but don't remove it from stack)
98
98
  void * stack_peek(
99
- stack * s //!< Stack to examine
99
+ stack * s //!< Stack to examine
100
100
  );
101
101
 
102
102
 
103
103
  /// Peek at a specific index in the stack
104
104
  void * stack_peek_index(
105
- stack * s, //!< Stack to examine
106
- size_t index //!< Index to peek at (0 is first pointer on stack)
105
+ stack * s, //!< Stack to examine
106
+ size_t index //!< Index to peek at (0 is first pointer on stack)
107
107
  );
108
108
 
109
109
 
@@ -109,9 +109,9 @@
109
109
  #include <curl/curl.h>
110
110
  #endif
111
111
 
112
- #include "textbundle.h"
112
+ #include "file.h"
113
113
  #include "miniz.h"
114
- #include "transclude.h"
114
+ #include "textbundle.h"
115
115
  #include "writer.h"
116
116
  #include "zip.h"
117
117
 
@@ -246,8 +246,6 @@ static void add_assets(mz_zip_archive * pZip, mmd_engine * e, const char * direc
246
246
  char destination[100] = "assets/";
247
247
  destination[43] = '\0';
248
248
 
249
- mz_bool status;
250
-
251
249
  HASH_ITER(hh, e->asset_hash, a, a_tmp) {
252
250
 
253
251
  memcpy(&destination[7], a->asset_path, 36);
@@ -190,7 +190,7 @@ token * token_new_parent(token * child, unsigned short type) {
190
190
  /// may or may not also be the start of a chain
191
191
  void token_chain_append(token * chain_start, token * t) {
192
192
  if ((chain_start == NULL) ||
193
- (t == NULL)) {
193
+ (t == NULL)) {
194
194
  return;
195
195
  }
196
196
 
@@ -369,6 +369,18 @@ token * token_prune_graft(token * first, token * last, unsigned short container_
369
369
  next->prev = first;
370
370
  }
371
371
 
372
+ // Fix tail (prior tail is now a child)
373
+ if (first->next == NULL) {
374
+ token * walker = first;
375
+
376
+ while (walker->prev) {
377
+ walker = walker->prev;
378
+ }
379
+
380
+ first->tail = first;
381
+ walker->tail = first;
382
+ }
383
+
372
384
  return first;
373
385
  }
374
386
 
@@ -465,15 +477,15 @@ void token_tree_describe(token * t, const char * string) {
465
477
  /// Find the child node of a given parent that contains the specified
466
478
  /// offset position.
467
479
  token * token_child_for_offset(
468
- token * parent, //!< Pointer to parent token
469
- size_t offset //!< Search position
480
+ token * parent, //!< Pointer to parent token
481
+ size_t offset //!< Search position
470
482
  ) {
471
483
  if (parent == NULL) {
472
484
  return NULL;
473
485
  }
474
486
 
475
487
  if ((parent->start > offset) ||
476
- (parent->start + parent->len < offset)) {
488
+ (parent->start + parent->len < offset)) {
477
489
  return NULL;
478
490
  }
479
491
 
@@ -505,16 +517,16 @@ static bool ranges_intersect(size_t start1, size_t len1, size_t start2, size_t l
505
517
  /// Find first child node of a given parent that intersects the specified
506
518
  /// offset range.
507
519
  token * token_first_child_in_range(
508
- token * parent, //!< Pointer to parent token
509
- size_t start, //!< Start search position
510
- size_t len //!< Search length
520
+ token * parent, //!< Pointer to parent token
521
+ size_t start, //!< Start search position
522
+ size_t len //!< Search length
511
523
  ) {
512
524
  if (parent == NULL) {
513
525
  return NULL;
514
526
  }
515
527
 
516
528
  if ((parent->start > start + len) ||
517
- (parent->start + parent->len < start)) {
529
+ (parent->start + parent->len < start)) {
518
530
  return NULL;
519
531
  }
520
532
 
@@ -539,16 +551,16 @@ token * token_first_child_in_range(
539
551
  /// Find last child node of a given parent that intersects the specified
540
552
  /// offset range.
541
553
  token * token_last_child_in_range(
542
- token * parent, //!< Pointer to parent token
543
- size_t start, //!< Start search position
544
- size_t len //!< Search length
554
+ token * parent, //!< Pointer to parent token
555
+ size_t start, //!< Start search position
556
+ size_t len //!< Search length
545
557
  ) {
546
558
  if (parent == NULL) {
547
559
  return NULL;
548
560
  }
549
561
 
550
562
  if ((parent->start > start + len) ||
551
- (parent->start + parent->len < start)) {
563
+ (parent->start + parent->len < start)) {
552
564
  return NULL;
553
565
  }
554
566
 
@@ -97,7 +97,7 @@ void token_pair_engine_free(token_pair_engine * e) {
97
97
 
98
98
  /// Add a new pairing configuration to a token pair engine
99
99
  void token_pair_engine_add_pairing(token_pair_engine * e, unsigned short open_type, unsigned short close_type,
100
- unsigned short pair_type, int options) {
100
+ unsigned short pair_type, int options) {
101
101
  // \todo: This needs to be more sophisticated
102
102
  e->can_open_pair[open_type] = 1;
103
103
  e->can_close_pair[close_type] = 1;
@@ -189,7 +189,7 @@ close:
189
189
  if (!e->empty_allowed[pair_type]) {
190
190
  // Make sure they aren't consecutive tokens
191
191
  if ((peek->next == walker) &&
192
- (peek->start + peek->len == walker->start)) {
192
+ (peek->start + peek->len == walker->start)) {
193
193
  // i--;
194
194
  i = start_counter; // In this situation, we can't use this token as a closer
195
195
  continue;
@@ -99,24 +99,24 @@ token_pair_engine * token_pair_engine_new(void);
99
99
 
100
100
  /// Free existing token pair engine
101
101
  void token_pair_engine_free(
102
- token_pair_engine * e //!< Token pair engine to be freed
102
+ token_pair_engine * e //!< Token pair engine to be freed
103
103
  );
104
104
 
105
105
  /// Add a new pairing configuration to a token pair engine
106
106
  void token_pair_engine_add_pairing(
107
- token_pair_engine * e, //!< Token pair engine to add to
108
- unsigned short open_type, //!< Token type for opener
109
- unsigned short close_type, //!< Token type for closer
110
- unsigned short pair_type, //!< Token type for pairing
111
- int options //!< Token pair options to use
107
+ token_pair_engine * e, //!< Token pair engine to add to
108
+ unsigned short open_type, //!< Token type for opener
109
+ unsigned short close_type, //!< Token type for closer
110
+ unsigned short pair_type, //!< Token type for pairing
111
+ int options //!< Token pair options to use
112
112
  );
113
113
 
114
114
  /// Search a token's childen for matching pairs
115
115
  void token_pairs_match_pairs_inside_token(
116
- token * parent, //!< Which tokens should we search for pairs
117
- token_pair_engine * e, //!< Token pair engine to be used for matching
118
- stack * s, //!< Pointer to a stack to use for pairing tokens
119
- unsigned short depth //!< Keep track of recursion depth
116
+ token * parent, //!< Which tokens should we search for pairs
117
+ token_pair_engine * e, //!< Token pair engine to be used for matching
118
+ stack * s, //!< Pointer to a stack to use for pairing tokens
119
+ unsigned short depth //!< Keep track of recursion depth
120
120
  );
121
121
 
122
122
 
@@ -56,45 +56,10 @@
56
56
  #include <string.h>
57
57
 
58
58
  #include "d_string.h"
59
+ #include "file.h"
59
60
  #include "libMultiMarkdown.h"
60
61
  #include "transclude.h"
61
62
 
62
- #if defined(__WIN32)
63
- #include <windows.h>
64
- #endif
65
-
66
- #define kBUFFERSIZE 4096 // How many bytes to read at a time
67
-
68
-
69
- /// strndup not available on all platforms
70
- static char * my_strndup(const char * source, size_t n) {
71
- if (source == NULL) {
72
- return NULL;
73
- }
74
-
75
- size_t len = 0;
76
- char * result;
77
- const char * test = source;
78
-
79
- // strlen is too slow if strlen(source) >> n
80
- for (len = 0; len < n; ++len) {
81
- if (test == '\0') {
82
- break;
83
- }
84
-
85
- test++;
86
- }
87
-
88
- result = malloc(len + 1);
89
-
90
- if (result) {
91
- memcpy(result, source, len);
92
- result[len] = '\0';
93
- }
94
-
95
- return result;
96
- }
97
-
98
63
 
99
64
  /// strdup() not available on all platforms
100
65
  static char * my_strdup(const char * source) {
@@ -108,191 +73,6 @@ static char * my_strdup(const char * source) {
108
73
  }
109
74
 
110
75
 
111
- /// Windows can use either `\` or `/` as a separator -- thanks to t-beckmann on github
112
- /// for suggesting a fix for this.
113
- bool is_separator(char c) {
114
- #if defined(__WIN32)
115
- return c == '\\' || c == '/';
116
- #else
117
- return c == '/';
118
- #endif
119
- }
120
-
121
-
122
- #ifdef TEST
123
- void Test_is_separator(CuTest* tc) {
124
- char * test = "a/\\";
125
-
126
- #if defined(__WIN32)
127
- CuAssertIntEquals(tc, false, is_separator(test[0]));
128
- CuAssertIntEquals(tc, true, is_separator(test[1]));
129
- CuAssertIntEquals(tc, true, is_separator(test[2]));
130
- #else
131
- CuAssertIntEquals(tc, false, is_separator(test[0]));
132
- CuAssertIntEquals(tc, true, is_separator(test[1]));
133
- CuAssertIntEquals(tc, false, is_separator(test[2]));
134
- #endif
135
- }
136
- #endif
137
-
138
-
139
- void add_trailing_sep(DString * path) {
140
- #if defined(__WIN32)
141
- char sep = '\\';
142
- #else
143
- char sep = '/';
144
- #endif
145
-
146
- // Ensure that folder ends in separator
147
- if (!is_separator(path->str[path->currentStringLength - 1])) {
148
- d_string_append_c(path, sep);
149
- }
150
- }
151
-
152
- /// Combine directory and base filename to create a full path */
153
- char * path_from_dir_base(const char * dir, const char * base) {
154
- if (!dir && !base) {
155
- return NULL;
156
- }
157
-
158
-
159
- DString * path = NULL;
160
- char * result = NULL;
161
-
162
- if ((base != NULL) && (is_separator(base[0]))) {
163
- // We have an absolute path
164
- path = d_string_new(base);
165
- } else {
166
- // We have a directory and relative path
167
- path = d_string_new(dir);
168
-
169
- // Ensure that folder ends in separator
170
- add_trailing_sep(path);
171
-
172
- // Append filename (if present)
173
- if (base) {
174
- d_string_append(path, base);
175
- }
176
- }
177
-
178
- result = path->str;
179
- d_string_free(path, false);
180
-
181
- return result;
182
- }
183
-
184
-
185
- #ifdef TEST
186
- void Test_path_from_dir_base(CuTest* tc) {
187
- char dir[10] = "/foo";
188
- char base[10] = "bar";
189
-
190
- char * path = path_from_dir_base(dir, base);
191
-
192
- #if defined(__WIN32)
193
- CuAssertStrEquals(tc, "/foo\\bar", path);
194
- #else
195
- CuAssertStrEquals(tc, "/foo/bar", path);
196
- #endif
197
-
198
- free(path);
199
- strcpy(base, "/bar");
200
-
201
- path = path_from_dir_base(dir, base);
202
-
203
- CuAssertStrEquals(tc, "/bar", path);
204
-
205
- free(path);
206
-
207
- path = path_from_dir_base(NULL, NULL);
208
- CuAssertStrEquals(tc, NULL, path);
209
- }
210
- #endif
211
-
212
-
213
- /// Separate filename and directory from a full path
214
- ///
215
- /// See http://stackoverflow.com/questions/1575278/function-to-split-a-filepath-into-path-and-file
216
- void split_path_file(char ** dir, char ** file, const char * path) {
217
- const char * slash = path, * next;
218
-
219
- #if defined(__WIN32)
220
- const char sep[] = "\\/"; // Windows allows either variant
221
- #else
222
- const char sep[] = "/";
223
- #endif
224
-
225
- while ((next = strpbrk(slash + 1, sep))) {
226
- slash = next;
227
- }
228
-
229
- if (path != slash) {
230
- slash++;
231
- }
232
-
233
- *dir = my_strndup(path, slash - path);
234
- *file = my_strdup(slash);
235
- }
236
-
237
- #ifdef TEST
238
- void Test_split_path_file(CuTest* tc) {
239
- char * dir, * file;
240
-
241
- char * path = "/foo/bar.txt";
242
- split_path_file(&dir, &file, path);
243
-
244
- CuAssertStrEquals(tc, "/foo/", dir);
245
- CuAssertStrEquals(tc, "bar.txt", file);
246
-
247
- path = "\\foo\\bar.txt";
248
- split_path_file(&dir, &file, path);
249
-
250
- #if defined(__WIN32)
251
- CuAssertStrEquals(tc, "\\foo\\", dir);
252
- CuAssertStrEquals(tc, "bar.txt", file);
253
- #else
254
- CuAssertStrEquals(tc, "", dir);
255
- CuAssertStrEquals(tc, "\\foo\\bar.txt", file);
256
- #endif
257
- }
258
- #endif
259
-
260
-
261
- DString * scan_file(const char * fname) {
262
- /* Read from a file and return a DString *
263
- `buffer` will need to be freed elsewhere */
264
-
265
- char chunk[kBUFFERSIZE];
266
- size_t bytes;
267
-
268
- FILE * file;
269
-
270
- #if defined(__WIN32)
271
- int wchars_num = MultiByteToWideChar(CP_UTF8, 0, fname, -1, NULL, 0);
272
- wchar_t wstr[wchars_num];
273
- MultiByteToWideChar(CP_UTF8, 0, fname, -1, wstr, wchars_num);
274
-
275
- if ((file = _wfopen(wstr, L"rb")) == NULL) {
276
- #else
277
-
278
- if ((file = fopen(fname, "r")) == NULL ) {
279
- #endif
280
-
281
- return NULL;
282
- }
283
-
284
- DString * buffer = d_string_new("");
285
-
286
- while ((bytes = fread(chunk, 1, kBUFFERSIZE, file)) > 0) {
287
- d_string_append_c_array(buffer, chunk, bytes);
288
- }
289
-
290
- fclose(file);
291
-
292
- return buffer;
293
- }
294
-
295
-
296
76
  /// Recursively transclude source text, given a search directory.
297
77
  /// Track files to prevent infinite recursive loops
298
78
  void mmd_transclude_source(DString * source, const char * search_path, const char * source_path, short format, stack * parsed, stack * manifest) {
@@ -467,11 +247,6 @@ void mmd_transclude_source(DString * source, const char * search_path, const cha
467
247
 
468
248
  if (mmd_engine_has_metadata(e, &offset)) {
469
249
  d_string_erase(buffer, 0, offset);
470
- } else {
471
- // Do we need to strip BOM?
472
- if (strncmp(buffer->str, "\xef\xbb\xbf", 3) == 0) {
473
- d_string_erase(buffer, 0, 3);
474
- }
475
250
  }
476
251
 
477
252
  mmd_engine_free(e, false);