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.
- checksums.yaml +4 -4
- data/ext/Makefile +2 -2
- data/ext/mmd/aho-corasick.c +12 -8
- data/ext/mmd/beamer.c +29 -0
- data/ext/mmd/critic_markup.c +100 -4
- data/ext/mmd/critic_markup.h +7 -0
- data/ext/mmd/d_string.c +502 -119
- data/ext/mmd/epub.c +2 -4
- data/ext/mmd/file.c +436 -0
- data/ext/mmd/file.h +153 -0
- data/ext/mmd/html.c +130 -37
- data/ext/mmd/include/d_string.h +20 -19
- data/ext/mmd/include/libMultiMarkdown.h +42 -27
- data/ext/mmd/include/token.h +15 -15
- data/ext/mmd/latex.c +107 -30
- data/ext/mmd/lexer.c +19 -7
- data/ext/mmd/lexer.h +2 -2
- data/ext/mmd/memoir.c +29 -0
- data/ext/mmd/mmd.c +65 -39
- data/ext/mmd/object_pool.h +4 -4
- data/ext/mmd/opendocument-content.c +95 -13
- data/ext/mmd/opendocument.c +315 -313
- data/ext/mmd/opml-lexer.c +2183 -0
- data/ext/mmd/opml-lexer.h +157 -0
- data/ext/mmd/opml-parser.c +1193 -0
- data/ext/mmd/opml-parser.h +15 -0
- data/ext/mmd/opml-reader.c +435 -0
- data/ext/mmd/opml-reader.h +111 -0
- data/ext/mmd/opml.c +511 -0
- data/ext/mmd/opml.h +115 -0
- data/ext/mmd/parser.c +2 -0
- data/ext/mmd/rng.c +1 -1
- data/ext/mmd/scanners.c +51663 -24824
- data/ext/mmd/stack.c +4 -2
- data/ext/mmd/stack.h +8 -8
- data/ext/mmd/textbundle.c +2 -4
- data/ext/mmd/token.c +24 -12
- data/ext/mmd/token_pairs.c +2 -2
- data/ext/mmd/token_pairs.h +10 -10
- data/ext/mmd/transclude.c +1 -226
- data/ext/mmd/transclude.h +0 -8
- data/ext/mmd/uuid.c +3 -3
- data/ext/mmd/version.h +3 -3
- data/ext/mmd/writer.c +99 -30
- data/ext/mmd/writer.h +11 -0
- data/lib/multi_markdown.bundle +0 -0
- data/lib/multi_markdown/version.rb +1 -1
- metadata +13 -5
- data/ext/mmd/fodt.c +0 -2288
- data/ext/mmd/fodt.h +0 -81
data/ext/mmd/stack.c
CHANGED
data/ext/mmd/stack.h
CHANGED
@@ -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
|
-
|
74
|
+
int startingSize //!< Default capacity for stack
|
75
75
|
);
|
76
76
|
|
77
77
|
|
78
78
|
/// Free the stack
|
79
79
|
void stack_free(
|
80
|
-
|
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
|
-
|
87
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
106
|
-
|
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
|
|
data/ext/mmd/textbundle.c
CHANGED
@@ -109,9 +109,9 @@
|
|
109
109
|
#include <curl/curl.h>
|
110
110
|
#endif
|
111
111
|
|
112
|
-
#include "
|
112
|
+
#include "file.h"
|
113
113
|
#include "miniz.h"
|
114
|
-
#include "
|
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);
|
data/ext/mmd/token.c
CHANGED
@@ -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
|
-
|
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
|
-
|
469
|
-
|
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
|
-
|
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
|
-
|
509
|
-
|
510
|
-
|
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
|
-
|
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
|
-
|
543
|
-
|
544
|
-
|
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
|
-
|
563
|
+
(parent->start + parent->len < start)) {
|
552
564
|
return NULL;
|
553
565
|
}
|
554
566
|
|
data/ext/mmd/token_pairs.c
CHANGED
@@ -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
|
-
|
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
|
-
|
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;
|
data/ext/mmd/token_pairs.h
CHANGED
@@ -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
|
-
|
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
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
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
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
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
|
|
data/ext/mmd/transclude.c
CHANGED
@@ -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);
|