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/lexer.c
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/* Generated by re2c 0.14.3 on
|
1
|
+
/* Generated by re2c 0.14.3 on Wed May 23 14:18:41 2018 */
|
2
2
|
/**
|
3
3
|
|
4
4
|
MultiMarkdown 6 -- Lightweight markup processor to produce HTML, LaTeX, and more.
|
@@ -643,6 +643,7 @@ yy53:
|
|
643
643
|
yyaccept = 8;
|
644
644
|
yych = *(YYMARKER = ++YYCURSOR);
|
645
645
|
switch (yych) {
|
646
|
+
case 0x00:
|
646
647
|
case '\t':
|
647
648
|
case '\n':
|
648
649
|
case '\r':
|
@@ -1088,6 +1089,7 @@ yy86:
|
|
1088
1089
|
YYCTXMARKER = YYCURSOR + 1;
|
1089
1090
|
yych = *++YYCURSOR;
|
1090
1091
|
switch (yych) {
|
1092
|
+
case 0x00:
|
1091
1093
|
case '\t':
|
1092
1094
|
case '\n':
|
1093
1095
|
case '\r':
|
@@ -1102,9 +1104,10 @@ yy87:
|
|
1102
1104
|
yych = *YYCURSOR;
|
1103
1105
|
yy88:
|
1104
1106
|
switch (yych) {
|
1107
|
+
case 0x00:
|
1108
|
+
case '\n': goto yy91;
|
1105
1109
|
case '\t':
|
1106
1110
|
case ' ': goto yy87;
|
1107
|
-
case '\n': goto yy91;
|
1108
1111
|
case '\r': goto yy93;
|
1109
1112
|
case 0xC2: goto yy90;
|
1110
1113
|
default: goto yy89;
|
@@ -1135,9 +1138,10 @@ yy94:
|
|
1135
1138
|
yych = *YYCURSOR;
|
1136
1139
|
yy95:
|
1137
1140
|
switch (yych) {
|
1141
|
+
case 0x00:
|
1142
|
+
case '\n': goto yy98;
|
1138
1143
|
case '\t':
|
1139
1144
|
case ' ': goto yy94;
|
1140
|
-
case '\n': goto yy98;
|
1141
1145
|
case '\r': goto yy100;
|
1142
1146
|
case 0xC2: goto yy97;
|
1143
1147
|
default: goto yy96;
|
@@ -1166,6 +1170,7 @@ yy101:
|
|
1166
1170
|
YYCTXMARKER = YYCURSOR + 1;
|
1167
1171
|
yych = *++YYCURSOR;
|
1168
1172
|
switch (yych) {
|
1173
|
+
case 0x00:
|
1169
1174
|
case '\t':
|
1170
1175
|
case '\n':
|
1171
1176
|
case '\r':
|
@@ -1178,6 +1183,7 @@ yy102:
|
|
1178
1183
|
YYCTXMARKER = YYCURSOR + 1;
|
1179
1184
|
yych = *++YYCURSOR;
|
1180
1185
|
switch (yych) {
|
1186
|
+
case 0x00:
|
1181
1187
|
case '\t':
|
1182
1188
|
case '\n':
|
1183
1189
|
case '\r':
|
@@ -1192,9 +1198,10 @@ yy103:
|
|
1192
1198
|
yych = *YYCURSOR;
|
1193
1199
|
yy104:
|
1194
1200
|
switch (yych) {
|
1201
|
+
case 0x00:
|
1202
|
+
case '\n': goto yy107;
|
1195
1203
|
case '\t':
|
1196
1204
|
case ' ': goto yy103;
|
1197
|
-
case '\n': goto yy107;
|
1198
1205
|
case '\r': goto yy109;
|
1199
1206
|
case 0xC2: goto yy106;
|
1200
1207
|
default: goto yy105;
|
@@ -1225,9 +1232,10 @@ yy110:
|
|
1225
1232
|
yych = *YYCURSOR;
|
1226
1233
|
yy111:
|
1227
1234
|
switch (yych) {
|
1235
|
+
case 0x00:
|
1236
|
+
case '\n': goto yy114;
|
1228
1237
|
case '\t':
|
1229
1238
|
case ' ': goto yy110;
|
1230
|
-
case '\n': goto yy114;
|
1231
1239
|
case '\r': goto yy116;
|
1232
1240
|
case 0xC2: goto yy113;
|
1233
1241
|
default: goto yy112;
|
@@ -1256,6 +1264,7 @@ yy117:
|
|
1256
1264
|
YYCTXMARKER = YYCURSOR + 1;
|
1257
1265
|
yych = *++YYCURSOR;
|
1258
1266
|
switch (yych) {
|
1267
|
+
case 0x00:
|
1259
1268
|
case '\t':
|
1260
1269
|
case '\n':
|
1261
1270
|
case '\r':
|
@@ -1268,6 +1277,7 @@ yy118:
|
|
1268
1277
|
YYCTXMARKER = YYCURSOR + 1;
|
1269
1278
|
yych = *++YYCURSOR;
|
1270
1279
|
switch (yych) {
|
1280
|
+
case 0x00:
|
1271
1281
|
case '\t':
|
1272
1282
|
case '\n':
|
1273
1283
|
case '\r':
|
@@ -1281,9 +1291,10 @@ yy119:
|
|
1281
1291
|
yych = *YYCURSOR;
|
1282
1292
|
yy120:
|
1283
1293
|
switch (yych) {
|
1294
|
+
case 0x00:
|
1295
|
+
case '\n': goto yy123;
|
1284
1296
|
case '\t':
|
1285
1297
|
case ' ': goto yy119;
|
1286
|
-
case '\n': goto yy123;
|
1287
1298
|
case '\r': goto yy125;
|
1288
1299
|
case 0xC2: goto yy122;
|
1289
1300
|
default: goto yy121;
|
@@ -1314,9 +1325,10 @@ yy126:
|
|
1314
1325
|
yych = *YYCURSOR;
|
1315
1326
|
yy127:
|
1316
1327
|
switch (yych) {
|
1328
|
+
case 0x00:
|
1329
|
+
case '\n': goto yy130;
|
1317
1330
|
case '\t':
|
1318
1331
|
case ' ': goto yy126;
|
1319
|
-
case '\n': goto yy130;
|
1320
1332
|
case '\r': goto yy132;
|
1321
1333
|
case 0xC2: goto yy129;
|
1322
1334
|
default: goto yy128;
|
data/ext/mmd/lexer.h
CHANGED
@@ -69,7 +69,7 @@ typedef struct Scanner Scanner;
|
|
69
69
|
|
70
70
|
/// Scan for the next token
|
71
71
|
int scan(
|
72
|
-
|
73
|
-
|
72
|
+
Scanner * s, //!< Pointer to Scanner state structure
|
73
|
+
const char * stop //!< Pointer to position in string at which to stop parsing
|
74
74
|
);
|
75
75
|
|
data/ext/mmd/memoir.c
CHANGED
@@ -55,6 +55,7 @@
|
|
55
55
|
|
56
56
|
#include "latex.h"
|
57
57
|
#include "memoir.h"
|
58
|
+
#include "parser.h"
|
58
59
|
|
59
60
|
#define print(x) d_string_append(out, x)
|
60
61
|
#define print_const(x) d_string_append_c_array(out, x, sizeof(x) - 1)
|
@@ -70,6 +71,7 @@ void mmd_export_token_memoir(DString * out, const char * source, token * t, scra
|
|
70
71
|
}
|
71
72
|
|
72
73
|
char * temp_char = NULL;
|
74
|
+
token * temp_token = NULL;
|
73
75
|
|
74
76
|
switch (t->type) {
|
75
77
|
case DOC_START_TOKEN:
|
@@ -82,6 +84,33 @@ void mmd_export_token_memoir(DString * out, const char * source, token * t, scra
|
|
82
84
|
temp_char = get_fence_language_specifier(t->child->child, source);
|
83
85
|
|
84
86
|
if (temp_char) {
|
87
|
+
if (strncmp("{=", temp_char, 2) == 0) {
|
88
|
+
// Raw source
|
89
|
+
if (raw_filter_text_matches(temp_char, FORMAT_MEMOIR)) {
|
90
|
+
switch (t->child->tail->type) {
|
91
|
+
case LINE_FENCE_BACKTICK_3:
|
92
|
+
case LINE_FENCE_BACKTICK_4:
|
93
|
+
case LINE_FENCE_BACKTICK_5:
|
94
|
+
temp_token = t->child->tail;
|
95
|
+
break;
|
96
|
+
|
97
|
+
default:
|
98
|
+
temp_token = NULL;
|
99
|
+
}
|
100
|
+
|
101
|
+
if (temp_token) {
|
102
|
+
d_string_append_c_array(out, &source[t->child->next->start], temp_token->start - t->child->next->start);
|
103
|
+
scratch->padded = 1;
|
104
|
+
} else {
|
105
|
+
d_string_append_c_array(out, &source[t->child->start + t->child->len], t->start + t->len - t->child->next->start);
|
106
|
+
scratch->padded = 0;
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
free(temp_char);
|
111
|
+
break;
|
112
|
+
}
|
113
|
+
|
85
114
|
printf("\\begin{adjustwidth}{2.5em}{2.5em}\n\\begin{lstlisting}[language=%s]\n", temp_char);
|
86
115
|
} else {
|
87
116
|
print_const("\\begin{adjustwidth}{2.5em}{2.5em}\n\\begin{verbatim}\n");
|
data/ext/mmd/mmd.c
CHANGED
@@ -65,6 +65,7 @@
|
|
65
65
|
#include "mmd.h"
|
66
66
|
#include "object_pool.h"
|
67
67
|
#include "opendocument.h"
|
68
|
+
#include "opml-reader.h"
|
68
69
|
#include "parser.h"
|
69
70
|
#include "scanners.h"
|
70
71
|
#include "stack.h"
|
@@ -115,6 +116,10 @@ mmd_engine * mmd_engine_create(DString * d, unsigned long extensions) {
|
|
115
116
|
|
116
117
|
e->allow_meta = (extensions & EXT_COMPATIBILITY) ? false : true;
|
117
118
|
|
119
|
+
if (e->allow_meta) {
|
120
|
+
e->allow_meta = (extensions & EXT_NO_METADATA) ? false : true;
|
121
|
+
}
|
122
|
+
|
118
123
|
e->language = LC_EN;
|
119
124
|
e->quotes_lang = ENGLISH;
|
120
125
|
|
@@ -237,7 +242,7 @@ void mmd_engine_set_language(mmd_engine * e, short language) {
|
|
237
242
|
break;
|
238
243
|
|
239
244
|
case LC_ES:
|
240
|
-
e->quotes_lang =
|
245
|
+
e->quotes_lang = SPANISH;
|
241
246
|
break;
|
242
247
|
|
243
248
|
case LC_FR:
|
@@ -506,20 +511,17 @@ void mmd_assign_line_type(mmd_engine * e, token * line) {
|
|
506
511
|
line->type = (first_child->type - HASH1) + LINE_ATX_1;
|
507
512
|
first_child->type = (line->type - LINE_ATX_1) + MARKER_H1;
|
508
513
|
|
509
|
-
// Strip trailing whitespace from '#' sequence
|
510
|
-
first_child->len = first_child->type - MARKER_H1 + 1;
|
511
|
-
|
512
514
|
// Strip trailing '#' sequence if present
|
513
515
|
if (line->child->tail->type == TEXT_NL) {
|
514
516
|
if ((line->child->tail->prev->type >= HASH1) &&
|
515
|
-
|
517
|
+
(line->child->tail->prev->type <= HASH6)) {
|
516
518
|
line->child->tail->prev->type -= HASH1;
|
517
519
|
line->child->tail->prev->type += MARKER_H1;
|
518
520
|
}
|
519
521
|
} else {
|
520
522
|
if ((line->child->tail->type >= HASH1) &&
|
521
|
-
|
522
|
-
line->child->tail->type -=
|
523
|
+
(line->child->tail->type <= HASH6)) {
|
524
|
+
line->child->tail->type -= HASH1;
|
523
525
|
line->child->tail->type += MARKER_H1;
|
524
526
|
}
|
525
527
|
}
|
@@ -572,8 +574,8 @@ void mmd_assign_line_type(mmd_engine * e, token * line) {
|
|
572
574
|
t = first_child;
|
573
575
|
|
574
576
|
while (t->next && ((t->next->type == INDENT_SPACE) ||
|
575
|
-
|
576
|
-
|
577
|
+
(t->next->type == INDENT_TAB) ||
|
578
|
+
(t->next->type == NON_INDENT_SPACE))) {
|
577
579
|
tokens_prune(t->next, t->next);
|
578
580
|
}
|
579
581
|
|
@@ -722,8 +724,8 @@ void mmd_assign_line_type(mmd_engine * e, token * line) {
|
|
722
724
|
t = first_child;
|
723
725
|
|
724
726
|
while (t->next && ((t->next->type == INDENT_SPACE) ||
|
725
|
-
|
726
|
-
|
727
|
+
(t->next->type == INDENT_TAB) ||
|
728
|
+
(t->next->type == NON_INDENT_SPACE))) {
|
727
729
|
tokens_prune(t->next, t->next);
|
728
730
|
}
|
729
731
|
|
@@ -832,7 +834,7 @@ void mmd_assign_line_type(mmd_engine * e, token * line) {
|
|
832
834
|
}
|
833
835
|
|
834
836
|
if ((line->type == LINE_PLAIN) &&
|
835
|
-
|
837
|
+
!(e->extensions & EXT_COMPATIBILITY)) {
|
836
838
|
// Check if this is a potential table line
|
837
839
|
token * walker = first_child;
|
838
840
|
|
@@ -966,6 +968,9 @@ token * mmd_tokenize_string(mmd_engine * e, size_t start, size_t len, bool stop_
|
|
966
968
|
// Reset metadata flag
|
967
969
|
e->allow_meta = (e->extensions & EXT_COMPATIBILITY) ? false : true;
|
968
970
|
|
971
|
+
if (e->allow_meta) {
|
972
|
+
e->allow_meta = (e->extensions & EXT_NO_METADATA) ? false : true;
|
973
|
+
}
|
969
974
|
|
970
975
|
// Create a scanner (for re2c)
|
971
976
|
Scanner s;
|
@@ -1253,7 +1258,7 @@ void mmd_assign_ambidextrous_tokens_in_block(mmd_engine * e, token * block, size
|
|
1253
1258
|
|
1254
1259
|
// Do we treat this like metadata?
|
1255
1260
|
if (!(e->extensions & EXT_COMPATIBILITY) &&
|
1256
|
-
|
1261
|
+
!(e->extensions & EXT_NO_METADATA)) {
|
1257
1262
|
break;
|
1258
1263
|
}
|
1259
1264
|
|
@@ -1281,6 +1286,9 @@ void mmd_assign_ambidextrous_tokens_in_block(mmd_engine * e, token * block, size
|
|
1281
1286
|
case BLOCK_SETEXT_1:
|
1282
1287
|
case BLOCK_SETEXT_2:
|
1283
1288
|
case BLOCK_TABLE:
|
1289
|
+
case BLOCK_TABLE_SECTION:
|
1290
|
+
case TABLE_ROW:
|
1291
|
+
case TABLE_CELL:
|
1284
1292
|
case BLOCK_TERM:
|
1285
1293
|
case LINE_LIST_BULLETED:
|
1286
1294
|
case LINE_LIST_ENUMERATED:
|
@@ -1478,14 +1486,14 @@ void mmd_assign_ambidextrous_tokens_in_block(mmd_engine * e, token * block, size
|
|
1478
1486
|
offset = t->start;
|
1479
1487
|
|
1480
1488
|
if (!((offset == 0) ||
|
1481
|
-
|
1482
|
-
|
1489
|
+
(char_is_whitespace_or_line_ending_or_punctuation(str[offset - 1])) ||
|
1490
|
+
(char_is_whitespace_or_line_ending_or_punctuation(str[offset + 1])))) {
|
1483
1491
|
t->type = APOSTROPHE;
|
1484
1492
|
break;
|
1485
1493
|
}
|
1486
1494
|
|
1487
1495
|
if (offset && (char_is_punctuation(str[offset - 1])) &&
|
1488
|
-
|
1496
|
+
(char_is_alphanumeric(str[offset + 1]))) {
|
1489
1497
|
// If possessive apostrophe, e.g. `x`'s
|
1490
1498
|
if (str[offset + 1] == 's' || str[offset + 1] == 'S') {
|
1491
1499
|
if (char_is_whitespace_or_line_ending_or_punctuation(str[offset + 2])) {
|
@@ -1520,7 +1528,7 @@ void mmd_assign_ambidextrous_tokens_in_block(mmd_engine * e, token * block, size
|
|
1520
1528
|
if (t->len == 1) {
|
1521
1529
|
// Check whether we have '1-2'
|
1522
1530
|
if ((offset == 0) || (!char_is_digit(str[offset - 1])) ||
|
1523
|
-
|
1531
|
+
(!char_is_digit(str[offset + 1]))) {
|
1524
1532
|
t->type = TEXT_PLAIN;
|
1525
1533
|
}
|
1526
1534
|
}
|
@@ -1566,18 +1574,14 @@ void mmd_assign_ambidextrous_tokens_in_block(mmd_engine * e, token * block, size
|
|
1566
1574
|
|
1567
1575
|
offset = t->start;
|
1568
1576
|
|
1569
|
-
//
|
1570
|
-
if ((offset == 0) || (char_is_whitespace_or_line_ending_or_punctuation(str[offset - 1]))) {
|
1571
|
-
t->can_open = 0;
|
1572
|
-
}
|
1573
|
-
|
1577
|
+
// Can't close if whitespace to left
|
1574
1578
|
if ((offset != 0) && (char_is_whitespace_or_line_ending(str[offset - 1]))) {
|
1575
1579
|
t->can_close = 0;
|
1576
1580
|
}
|
1577
1581
|
|
1578
1582
|
offset = t->start + t->len;
|
1579
1583
|
|
1580
|
-
if (
|
1584
|
+
if (char_is_whitespace_or_line_ending(str[offset])) {
|
1581
1585
|
t->can_open = 0;
|
1582
1586
|
}
|
1583
1587
|
|
@@ -1661,11 +1665,11 @@ void pair_emphasis_tokens(token * t) {
|
|
1661
1665
|
closer = t->mate;
|
1662
1666
|
|
1663
1667
|
if (t->next &&
|
1664
|
-
|
1665
|
-
|
1666
|
-
|
1667
|
-
|
1668
|
-
|
1668
|
+
(t->next->mate == closer->prev) &&
|
1669
|
+
(t->type == t->next->type) &&
|
1670
|
+
(t->next->mate != t) &&
|
1671
|
+
(t->start + t->len == t->next->start) &&
|
1672
|
+
(closer->start == closer->prev->start + closer->prev->len)) {
|
1669
1673
|
|
1670
1674
|
// We have a strong pair
|
1671
1675
|
t->type = STRONG_START;
|
@@ -1788,8 +1792,8 @@ void is_list_loose(token * list) {
|
|
1788
1792
|
/// Is this actually an HTML block?
|
1789
1793
|
void is_para_html(mmd_engine * e, token * block) {
|
1790
1794
|
if ((block == NULL) ||
|
1791
|
-
|
1792
|
-
|
1795
|
+
(block->child == NULL) ||
|
1796
|
+
(block->child->type != LINE_PLAIN)) {
|
1793
1797
|
return;
|
1794
1798
|
}
|
1795
1799
|
|
@@ -2043,7 +2047,7 @@ void strip_line_tokens_from_block(mmd_engine * e, token * block) {
|
|
2043
2047
|
case LINE_SETEXT_1:
|
2044
2048
|
case LINE_SETEXT_2:
|
2045
2049
|
if ((block->type == BLOCK_SETEXT_1) ||
|
2046
|
-
|
2050
|
+
(block->type == BLOCK_SETEXT_2)) {
|
2047
2051
|
temp = l->next;
|
2048
2052
|
tokens_prune(l, l);
|
2049
2053
|
l = temp;
|
@@ -2088,7 +2092,7 @@ handle_line:
|
|
2088
2092
|
|
2089
2093
|
// If we're not a code block, strip additional indents
|
2090
2094
|
if ((block->type != BLOCK_CODE_INDENTED) &&
|
2091
|
-
|
2095
|
+
(block->type != BLOCK_CODE_FENCED)) {
|
2092
2096
|
while (l->child && ((l->child->type == INDENT_SPACE) || (l->child->type == INDENT_TAB))) {
|
2093
2097
|
token_remove_first_child(l);
|
2094
2098
|
}
|
@@ -2123,7 +2127,7 @@ handle_line:
|
|
2123
2127
|
|
2124
2128
|
// Move children to parent
|
2125
2129
|
// Add ':' back
|
2126
|
-
if (e->dstr->str[l->child->start - 1] == ':') {
|
2130
|
+
if (l->child->start > 0 && e->dstr->str[l->child->start - 1] == ':') {
|
2127
2131
|
temp = token_new(COLON, l->child->start - 1, 1);
|
2128
2132
|
token_append_child(block, temp);
|
2129
2133
|
}
|
@@ -2184,6 +2188,10 @@ token * mmd_engine_parse_substring(mmd_engine * e, size_t byte_start, size_t byt
|
|
2184
2188
|
e->extensions |= EXT_NO_METADATA;
|
2185
2189
|
}
|
2186
2190
|
|
2191
|
+
if (e->extensions & EXT_PARSE_OPML) {
|
2192
|
+
// Convert from OPML first (if not done earlier)
|
2193
|
+
mmd_convert_opml_string(e, byte_start, byte_len);
|
2194
|
+
}
|
2187
2195
|
|
2188
2196
|
// Tokenize the string
|
2189
2197
|
token * doc = mmd_tokenize_string(e, byte_start, byte_len, false);
|
@@ -2259,6 +2267,7 @@ bool mmd_d_string_has_metadata(DString * source, size_t * end) {
|
|
2259
2267
|
/// Does the text have metadata?
|
2260
2268
|
bool mmd_engine_has_metadata(mmd_engine * e, size_t * end) {
|
2261
2269
|
bool result = false;
|
2270
|
+
token * old_root;
|
2262
2271
|
|
2263
2272
|
if (!e) {
|
2264
2273
|
return false;
|
@@ -2275,10 +2284,8 @@ bool mmd_engine_has_metadata(mmd_engine * e, size_t * end) {
|
|
2275
2284
|
return false;
|
2276
2285
|
}
|
2277
2286
|
|
2278
|
-
//
|
2279
|
-
|
2280
|
-
token_tree_free(e->root);
|
2281
|
-
}
|
2287
|
+
// Preserve existing parse tree (if any)
|
2288
|
+
old_root = e->root;
|
2282
2289
|
|
2283
2290
|
// Tokenize the string (up until first empty line)
|
2284
2291
|
token * doc = mmd_tokenize_string(e, 0, e->dstr->currentStringLength, true);
|
@@ -2298,6 +2305,9 @@ bool mmd_engine_has_metadata(mmd_engine * e, size_t * end) {
|
|
2298
2305
|
token_tree_free(doc);
|
2299
2306
|
}
|
2300
2307
|
|
2308
|
+
// Restore previous parse tree
|
2309
|
+
e->root = old_root;
|
2310
|
+
|
2301
2311
|
return result;
|
2302
2312
|
}
|
2303
2313
|
|
@@ -2399,6 +2409,10 @@ char * mmd_d_string_metavalue_for_key(DString * source, const char * key) {
|
|
2399
2409
|
/// Grab metadata without processing entire document
|
2400
2410
|
/// Returned char * does not need to be freed
|
2401
2411
|
char * mmd_engine_metavalue_for_key(mmd_engine * e, const char * key) {
|
2412
|
+
if (e == NULL || key == NULL) {
|
2413
|
+
return NULL;
|
2414
|
+
}
|
2415
|
+
|
2402
2416
|
if (e->metadata_stack->size == 0) {
|
2403
2417
|
// Ensure we have checked for metadata
|
2404
2418
|
if (!mmd_engine_has_metadata(e, NULL)) {
|
@@ -2538,7 +2552,11 @@ void mmd_engine_update_metavalue_for_key(mmd_engine * e, const char * key, const
|
|
2538
2552
|
|
2539
2553
|
DString * temp = d_string_new(key);
|
2540
2554
|
d_string_append(temp, ":\t");
|
2541
|
-
|
2555
|
+
|
2556
|
+
if (value) {
|
2557
|
+
d_string_append(temp, value);
|
2558
|
+
}
|
2559
|
+
|
2542
2560
|
d_string_append_c(temp, '\n');
|
2543
2561
|
|
2544
2562
|
if (start != -1) {
|
@@ -2568,7 +2586,10 @@ void mmd_engine_update_metavalue_for_key(mmd_engine * e, const char * key, const
|
|
2568
2586
|
|
2569
2587
|
d_string_erase(e->dstr, start, len);
|
2570
2588
|
d_string_insert(e->dstr, start, "\n");
|
2571
|
-
|
2589
|
+
|
2590
|
+
if (value) {
|
2591
|
+
d_string_insert(e->dstr, start, value);
|
2592
|
+
}
|
2572
2593
|
} else if (meta_end != 0) {
|
2573
2594
|
// We're appending metadata at the end
|
2574
2595
|
d_string_insert(e->dstr, meta_end, temp->str);
|
@@ -2743,6 +2764,11 @@ DString * mmd_engine_convert_to_data(mmd_engine * e, short format, const char *
|
|
2743
2764
|
DString * result = NULL;
|
2744
2765
|
|
2745
2766
|
if (format == FORMAT_MMD) {
|
2767
|
+
if (e->extensions & EXT_PARSE_OPML) {
|
2768
|
+
// Convert from OPML first (if not done earlier)
|
2769
|
+
mmd_convert_opml_string(e, 0, e->dstr->currentStringLength);
|
2770
|
+
}
|
2771
|
+
|
2746
2772
|
// Simply return text (transclusion is handled externally)
|
2747
2773
|
d_string_append_c_array(output, e->dstr->str, e->dstr->currentStringLength);
|
2748
2774
|
|