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.
- 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);
|