rmultimarkdown 6.2.2.1 → 6.4.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 (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);