greenmat 3.2.2.4 → 3.5.1.0
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/.travis.yml +19 -4
- data/CHANGELOG.md +4 -0
- data/COPYING +17 -11
- data/Gemfile +2 -2
- data/README.md +19 -13
- data/bin/greenmat +4 -40
- data/ext/greenmat/autolink.c +24 -12
- data/ext/greenmat/buffer.c +24 -17
- data/ext/greenmat/buffer.h +18 -13
- data/ext/greenmat/gm_markdown.c +35 -13
- data/ext/greenmat/gm_render.c +60 -21
- data/ext/greenmat/greenmat.h +22 -0
- data/ext/greenmat/houdini.h +22 -0
- data/ext/greenmat/houdini_href_e.c +27 -11
- data/ext/greenmat/houdini_html_e.c +22 -1
- data/ext/greenmat/html.c +127 -45
- data/ext/greenmat/html.h +19 -14
- data/ext/greenmat/html_blocks.h +68 -70
- data/ext/greenmat/html_smartypants.c +47 -20
- data/ext/greenmat/markdown.c +42 -30
- data/ext/greenmat/markdown.h +17 -15
- data/ext/greenmat/stack.c +22 -0
- data/ext/greenmat/stack.h +22 -0
- data/greenmat.gemspec +3 -3
- data/lib/greenmat.rb +1 -1
- data/lib/greenmat/cli.rb +86 -0
- data/lib/greenmat/compat.rb +0 -5
- data/lib/greenmat/render_strip.rb +13 -1
- data/lib/greenmat/version.rb +1 -1
- data/test/custom_render_test.rb +41 -2
- data/test/greenmat_bin_test.rb +80 -0
- data/test/greenmat_compat_test.rb +6 -6
- data/test/html5_test.rb +51 -38
- data/test/html_render_test.rb +161 -127
- data/test/html_toc_render_test.rb +74 -11
- data/test/markdown_test.rb +258 -182
- data/test/safe_render_test.rb +5 -6
- data/test/smarty_html_test.rb +19 -13
- data/test/smarty_pants_test.rb +10 -0
- data/test/stripdown_render_test.rb +38 -9
- data/test/test_helper.rb +30 -9
- metadata +15 -13
data/ext/greenmat/html.h
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c)
|
2
|
+
* Copyright (c) 2015, Vicent Marti
|
3
3
|
*
|
4
|
-
* Permission
|
5
|
-
*
|
6
|
-
*
|
4
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
* of this software and associated documentation files (the "Software"), to deal
|
6
|
+
* in the Software without restriction, including without limitation the rights
|
7
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
* copies of the Software, and to permit persons to whom the Software is
|
9
|
+
* furnished to do so, subject to the following conditions:
|
7
10
|
*
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
14
|
-
* OR
|
11
|
+
* The above copyright notice and this permission notice shall be included in
|
12
|
+
* all copies or substantial portions of the Software.
|
13
|
+
*
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
* THE SOFTWARE.
|
15
21
|
*/
|
16
22
|
|
17
23
|
#ifndef HTML_H__
|
@@ -29,7 +35,7 @@ struct html_renderopt {
|
|
29
35
|
struct {
|
30
36
|
int current_level;
|
31
37
|
int level_offset;
|
32
|
-
int
|
38
|
+
int nesting_bounds[2];
|
33
39
|
} toc_data;
|
34
40
|
|
35
41
|
unsigned int flags;
|
@@ -65,7 +71,7 @@ extern void
|
|
65
71
|
sdhtml_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, unsigned int render_flags);
|
66
72
|
|
67
73
|
extern void
|
68
|
-
sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, int
|
74
|
+
sdhtml_toc_renderer(struct sd_callbacks *callbacks, struct html_renderopt *options_ptr, unsigned int render_flags);
|
69
75
|
|
70
76
|
extern void
|
71
77
|
sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size);
|
@@ -75,4 +81,3 @@ sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size);
|
|
75
81
|
#endif
|
76
82
|
|
77
83
|
#endif
|
78
|
-
|
data/ext/greenmat/html_blocks.h
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
/* C code produced by gperf version 3.0.
|
1
|
+
/* C code produced by gperf version 3.0.3 */
|
2
2
|
/* Command-line: gperf -N find_block_tag -H hash_block_tag -C -c -E --ignore-case html_block_names.txt */
|
3
|
-
/* See
|
3
|
+
/* See https://git.io/vPLqa for the list of recognized elements */
|
4
4
|
/* Computed positions: -k'1-2' */
|
5
5
|
|
6
6
|
#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
|
@@ -30,7 +30,7 @@
|
|
30
30
|
error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
|
31
31
|
#endif
|
32
32
|
|
33
|
-
/* maximum key range =
|
33
|
+
/* maximum key range = 72, duplicates = 0 */
|
34
34
|
|
35
35
|
#ifndef GPERF_DOWNCASE
|
36
36
|
#define GPERF_DOWNCASE 1
|
@@ -94,34 +94,34 @@ hash_block_tag (str, len)
|
|
94
94
|
{
|
95
95
|
static const unsigned char asso_values[] =
|
96
96
|
{
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
0,
|
105
|
-
0,
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
97
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
98
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
99
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
100
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
101
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
102
|
+
26, 60, 55, 45, 40, 35, 73, 73, 73, 73,
|
103
|
+
73, 73, 73, 73, 73, 20, 15, 15, 0, 35,
|
104
|
+
0, 25, 10, 10, 5, 73, 73, 0, 15, 15,
|
105
|
+
0, 73, 73, 15, 20, 10, 10, 73, 73, 73,
|
106
|
+
73, 73, 73, 73, 73, 73, 73, 20, 15, 15,
|
107
|
+
0, 35, 0, 25, 10, 10, 5, 73, 73, 0,
|
108
|
+
15, 15, 0, 73, 73, 15, 20, 10, 10, 73,
|
109
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
110
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
111
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
112
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
113
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
114
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
115
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
116
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
117
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
118
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
119
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
120
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
121
|
+
73, 73, 73, 73, 73, 73, 73, 73, 73, 73,
|
122
|
+
73, 73, 73, 73, 73, 73, 73
|
123
123
|
};
|
124
|
-
register int hval = len;
|
124
|
+
register unsigned int hval = len;
|
125
125
|
|
126
126
|
switch (hval)
|
127
127
|
{
|
@@ -135,12 +135,6 @@ hash_block_tag (str, len)
|
|
135
135
|
return hval;
|
136
136
|
}
|
137
137
|
|
138
|
-
#ifdef __GNUC__
|
139
|
-
__inline
|
140
|
-
#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
|
141
|
-
__attribute__ ((__gnu_inline__))
|
142
|
-
#endif
|
143
|
-
#endif
|
144
138
|
const char *
|
145
139
|
find_block_tag (str, len)
|
146
140
|
register const char *str;
|
@@ -148,76 +142,80 @@ find_block_tag (str, len)
|
|
148
142
|
{
|
149
143
|
enum
|
150
144
|
{
|
151
|
-
TOTAL_KEYWORDS =
|
145
|
+
TOTAL_KEYWORDS = 43,
|
152
146
|
MIN_WORD_LENGTH = 1,
|
153
147
|
MAX_WORD_LENGTH = 10,
|
154
148
|
MIN_HASH_VALUE = 1,
|
155
|
-
MAX_HASH_VALUE =
|
149
|
+
MAX_HASH_VALUE = 72
|
156
150
|
};
|
157
151
|
|
158
152
|
static const char * const wordlist[] =
|
159
153
|
{
|
160
154
|
"",
|
161
155
|
"p",
|
162
|
-
"
|
163
|
-
"
|
156
|
+
"dl",
|
157
|
+
"del",
|
164
158
|
"form",
|
165
|
-
"
|
159
|
+
"",
|
166
160
|
"footer",
|
167
|
-
"
|
168
|
-
"",
|
161
|
+
"details",
|
162
|
+
"div",
|
163
|
+
"", "",
|
169
164
|
"figure",
|
170
|
-
"
|
165
|
+
"ul",
|
171
166
|
"fieldset",
|
172
|
-
"
|
167
|
+
"",
|
173
168
|
"figcaption",
|
174
169
|
"header",
|
175
|
-
"
|
176
|
-
"
|
177
|
-
"",
|
178
|
-
"
|
170
|
+
"ol",
|
171
|
+
"pre",
|
172
|
+
"math",
|
173
|
+
"video",
|
179
174
|
"script",
|
180
|
-
"
|
181
|
-
"
|
175
|
+
"section",
|
176
|
+
"noscript",
|
182
177
|
"",
|
183
|
-
"
|
178
|
+
"blockquote",
|
184
179
|
"hgroup",
|
185
|
-
"
|
186
|
-
"
|
187
|
-
"",
|
180
|
+
"hr",
|
181
|
+
"ins",
|
182
|
+
"",
|
183
|
+
"style",
|
184
|
+
"output",
|
185
|
+
"summary",
|
186
|
+
"nav",
|
187
|
+
"",
|
188
|
+
"audio",
|
188
189
|
"canvas",
|
189
190
|
"dd",
|
190
|
-
"
|
191
|
+
"h1",
|
191
192
|
"abbr",
|
192
|
-
"audio",
|
193
|
-
"iframe",
|
194
|
-
"address",
|
195
|
-
"ins",
|
196
|
-
"",
|
197
193
|
"table",
|
198
|
-
"",
|
199
|
-
"
|
194
|
+
"iframe",
|
195
|
+
"article",
|
200
196
|
"", "",
|
201
197
|
"aside",
|
202
|
-
"
|
203
|
-
"
|
198
|
+
"",
|
199
|
+
"h6",
|
204
200
|
"", "",
|
205
201
|
"tfoot",
|
206
202
|
"",
|
203
|
+
"h5",
|
204
|
+
"", "", "", "",
|
207
205
|
"h4",
|
208
206
|
"", "", "", "",
|
209
|
-
"
|
207
|
+
"address",
|
210
208
|
"", "", "", "",
|
211
|
-
"
|
209
|
+
"h3",
|
212
210
|
"", "", "", "",
|
213
|
-
"
|
211
|
+
"h2"
|
214
212
|
};
|
215
213
|
|
216
214
|
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
|
217
215
|
{
|
218
|
-
|
216
|
+
unsigned int key = hash_block_tag (str, len);
|
219
217
|
|
220
|
-
if (key <= MAX_HASH_VALUE
|
218
|
+
if (key <= MAX_HASH_VALUE)
|
221
219
|
{
|
222
220
|
register const char *s = wordlist[key];
|
223
221
|
|
@@ -1,17 +1,23 @@
|
|
1
1
|
/*
|
2
|
-
* Copyright (c)
|
2
|
+
* Copyright (c) 2015, Vicent Marti
|
3
3
|
*
|
4
|
-
* Permission
|
5
|
-
*
|
6
|
-
*
|
4
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
* of this software and associated documentation files (the "Software"), to deal
|
6
|
+
* in the Software without restriction, including without limitation the rights
|
7
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
* copies of the Software, and to permit persons to whom the Software is
|
9
|
+
* furnished to do so, subject to the following conditions:
|
7
10
|
*
|
8
|
-
*
|
9
|
-
*
|
10
|
-
*
|
11
|
-
*
|
12
|
-
*
|
13
|
-
*
|
14
|
-
* OR
|
11
|
+
* The above copyright notice and this permission notice shall be included in
|
12
|
+
* all copies or substantial portions of the Software.
|
13
|
+
*
|
14
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
17
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
18
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
19
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
20
|
+
* THE SOFTWARE.
|
15
21
|
*/
|
16
22
|
|
17
23
|
#include "buffer.h"
|
@@ -83,6 +89,12 @@ word_boundary(uint8_t c)
|
|
83
89
|
return c == 0 || isspace(c) || ispunct(c);
|
84
90
|
}
|
85
91
|
|
92
|
+
static inline int
|
93
|
+
fraction_boundary(uint8_t c)
|
94
|
+
{
|
95
|
+
return c == 0 || isspace(c) || (c != '/' && ispunct(c));
|
96
|
+
}
|
97
|
+
|
86
98
|
// If 'text' begins with any kind of single quote (e.g. "'" or "'" etc.),
|
87
99
|
// returns the length of the sequence of characters that makes up the single-
|
88
100
|
// quote. Otherwise, returns zero.
|
@@ -139,6 +151,9 @@ smartypants_squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previo
|
|
139
151
|
return next_squote_len;
|
140
152
|
}
|
141
153
|
|
154
|
+
if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
|
155
|
+
return 0;
|
156
|
+
|
142
157
|
// trailing single quotes: students', tryin'
|
143
158
|
if (word_boundary(t1)) {
|
144
159
|
BUFPUTSL(ob, "’");
|
@@ -166,9 +181,6 @@ smartypants_squote(struct buf *ob, struct smartypants_data *smrt, uint8_t previo
|
|
166
181
|
}
|
167
182
|
}
|
168
183
|
|
169
|
-
if (smartypants_quotes(ob, previous_char, size > 0 ? text[1] : 0, 's', &smrt->in_squote))
|
170
|
-
return 0;
|
171
|
-
|
172
184
|
bufput(ob, squote_text, squote_size);
|
173
185
|
return 0;
|
174
186
|
}
|
@@ -282,16 +294,16 @@ smartypants_cb__backtick(struct buf *ob, struct smartypants_data *smrt, uint8_t
|
|
282
294
|
static size_t
|
283
295
|
smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, uint8_t previous_char, const uint8_t *text, size_t size)
|
284
296
|
{
|
285
|
-
if (
|
297
|
+
if (fraction_boundary(previous_char) && size >= 3) {
|
286
298
|
if (text[0] == '1' && text[1] == '/' && text[2] == '2') {
|
287
|
-
if (size == 3 ||
|
299
|
+
if (size == 3 || fraction_boundary(text[3])) {
|
288
300
|
BUFPUTSL(ob, "½");
|
289
301
|
return 2;
|
290
302
|
}
|
291
303
|
}
|
292
304
|
|
293
305
|
if (text[0] == '1' && text[1] == '/' && text[2] == '4') {
|
294
|
-
if (size == 3 ||
|
306
|
+
if (size == 3 || fraction_boundary(text[3]) ||
|
295
307
|
(size >= 5 && tolower(text[3]) == 't' && tolower(text[4]) == 'h')) {
|
296
308
|
BUFPUTSL(ob, "¼");
|
297
309
|
return 2;
|
@@ -299,7 +311,7 @@ smartypants_cb__number(struct buf *ob, struct smartypants_data *smrt, uint8_t pr
|
|
299
311
|
}
|
300
312
|
|
301
313
|
if (text[0] == '3' && text[1] == '/' && text[2] == '4') {
|
302
|
-
if (size == 3 ||
|
314
|
+
if (size == 3 || fraction_boundary(text[3]) ||
|
303
315
|
(size >= 6 && tolower(text[3]) == 't' && tolower(text[4]) == 'h' && tolower(text[5]) == 's')) {
|
304
316
|
BUFPUTSL(ob, "¾");
|
305
317
|
return 2;
|
@@ -329,6 +341,7 @@ smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t prev
|
|
329
341
|
};
|
330
342
|
static const size_t skip_tags_count = 8;
|
331
343
|
|
344
|
+
size_t next_to_closing_a = 0;
|
332
345
|
size_t tag, i = 0;
|
333
346
|
|
334
347
|
while (i < size && text[i] != '>')
|
@@ -357,7 +370,23 @@ smartypants_cb__ltag(struct buf *ob, struct smartypants_data *smrt, uint8_t prev
|
|
357
370
|
i++;
|
358
371
|
}
|
359
372
|
|
373
|
+
if (sdhtml_is_tag(text, size, "a") == HTML_TAG_CLOSE) {
|
374
|
+
while (i < size && text[i] != '>')
|
375
|
+
i++;
|
376
|
+
|
377
|
+
next_to_closing_a = 1;
|
378
|
+
}
|
379
|
+
|
360
380
|
bufput(ob, text, i + 1);
|
381
|
+
|
382
|
+
// Pretty tricky: since people may refer to something or someone
|
383
|
+
// with a link but use the possessive form right after it, we need
|
384
|
+
// to check whether a single quote is next to a closing "</a"> tag.
|
385
|
+
if (next_to_closing_a && strncmp("'", text+(i+1), 5) == 0) {
|
386
|
+
bufput(ob, "’", 7);
|
387
|
+
i += 5;
|
388
|
+
}
|
389
|
+
|
361
390
|
return i;
|
362
391
|
}
|
363
392
|
|
@@ -441,5 +470,3 @@ sdhtml_smartypants(struct buf *ob, const uint8_t *text, size_t size)
|
|
441
470
|
}
|
442
471
|
}
|
443
472
|
}
|
444
|
-
|
445
|
-
|
data/ext/greenmat/markdown.c
CHANGED
@@ -1,20 +1,24 @@
|
|
1
|
-
/* markdown.c - generic markdown parser */
|
2
|
-
|
3
1
|
/*
|
4
2
|
* Copyright (c) 2009, Natacha Porté
|
5
|
-
* Copyright (c)
|
3
|
+
* Copyright (c) 2015, Vicent Marti
|
4
|
+
*
|
5
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
* of this software and associated documentation files (the "Software"), to deal
|
7
|
+
* in the Software without restriction, including without limitation the rights
|
8
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
* copies of the Software, and to permit persons to whom the Software is
|
10
|
+
* furnished to do so, subject to the following conditions:
|
6
11
|
*
|
7
|
-
*
|
8
|
-
*
|
9
|
-
* copyright notice and this permission notice appear in all copies.
|
12
|
+
* The above copyright notice and this permission notice shall be included in
|
13
|
+
* all copies or substantial portions of the Software.
|
10
14
|
*
|
11
|
-
* THE SOFTWARE IS PROVIDED "AS IS"
|
12
|
-
*
|
13
|
-
*
|
14
|
-
*
|
15
|
-
*
|
16
|
-
*
|
17
|
-
*
|
15
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
* THE SOFTWARE.
|
18
22
|
*/
|
19
23
|
|
20
24
|
#include "markdown.h"
|
@@ -88,7 +92,6 @@ typedef size_t
|
|
88
92
|
|
89
93
|
static size_t char_emphasis(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
|
90
94
|
static size_t char_underline(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
|
91
|
-
static size_t char_highlight(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
|
92
95
|
static size_t char_quote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
|
93
96
|
static size_t char_linebreak(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
|
94
97
|
static size_t char_codespan(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size);
|
@@ -467,7 +470,7 @@ tag_length(uint8_t *data, size_t size, enum mkd_autolink *autolink)
|
|
467
470
|
static void
|
468
471
|
parse_inline(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
|
469
472
|
{
|
470
|
-
size_t i = 0, end = 0;
|
473
|
+
size_t i = 0, end = 0, consumed = 0;
|
471
474
|
uint8_t action = 0;
|
472
475
|
struct buf work = { 0, 0, 0, 0 };
|
473
476
|
|
@@ -492,12 +495,13 @@ parse_inline(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t siz
|
|
492
495
|
if (end >= size) break;
|
493
496
|
i = end;
|
494
497
|
|
495
|
-
end = markdown_char_ptrs[(int)action](ob, rndr, data + i, i, size - i);
|
498
|
+
end = markdown_char_ptrs[(int)action](ob, rndr, data + i, i - consumed, size - i);
|
496
499
|
if (!end) /* no action from the callback */
|
497
500
|
end = i + 1;
|
498
501
|
else {
|
499
502
|
i += end;
|
500
503
|
end = i;
|
504
|
+
consumed = i;
|
501
505
|
}
|
502
506
|
}
|
503
507
|
}
|
@@ -646,7 +650,7 @@ parse_emph1(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size
|
|
646
650
|
if (data[i] == c && !_isspace(data[i - 1])) {
|
647
651
|
|
648
652
|
if (rndr->ext_flags & MKDEXT_NO_INTRA_EMPHASIS) {
|
649
|
-
if (i +
|
653
|
+
if (i + 1 < size && _isalnum(data[i + 1]))
|
650
654
|
continue;
|
651
655
|
}
|
652
656
|
|
@@ -898,7 +902,6 @@ char_quote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offse
|
|
898
902
|
return end;
|
899
903
|
}
|
900
904
|
|
901
|
-
|
902
905
|
/* char_escape • '\\' backslash escape */
|
903
906
|
static size_t
|
904
907
|
char_escape(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset, size_t size)
|
@@ -1176,7 +1179,7 @@ char_link(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t offset
|
|
1176
1179
|
title_e--;
|
1177
1180
|
|
1178
1181
|
/* checking for closing quote presence */
|
1179
|
-
if (data[title_e] != '\'' &&
|
1182
|
+
if (data[title_e] != '\'' && data[title_e] != '"') {
|
1180
1183
|
title_b = title_e = 0;
|
1181
1184
|
link_e = i;
|
1182
1185
|
}
|
@@ -1605,7 +1608,7 @@ prefix_oli(uint8_t *data, size_t size)
|
|
1605
1608
|
return i + 2;
|
1606
1609
|
}
|
1607
1610
|
|
1608
|
-
/* prefix_uli • returns
|
1611
|
+
/* prefix_uli • returns unordered list item prefix */
|
1609
1612
|
static size_t
|
1610
1613
|
prefix_uli(uint8_t *data, size_t size)
|
1611
1614
|
{
|
@@ -1677,7 +1680,7 @@ parse_blockquote(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t
|
|
1677
1680
|
static size_t
|
1678
1681
|
parse_htmlblock(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size, int do_render);
|
1679
1682
|
|
1680
|
-
/*
|
1683
|
+
/* parse_paragraph • handles parsing of a regular paragraph */
|
1681
1684
|
static size_t
|
1682
1685
|
parse_paragraph(struct buf *ob, struct sd_markdown *rndr, uint8_t *data, size_t size)
|
1683
1686
|
{
|
@@ -2392,7 +2395,7 @@ parse_table_header(
|
|
2392
2395
|
if (i < under_end && data[i] != '|' && data[i] != '+')
|
2393
2396
|
break;
|
2394
2397
|
|
2395
|
-
if (dashes <
|
2398
|
+
if (dashes < 1)
|
2396
2399
|
break;
|
2397
2400
|
|
2398
2401
|
i++;
|
@@ -2810,10 +2813,13 @@ sd_markdown_new(
|
|
2810
2813
|
if (md->cb.emphasis || md->cb.double_emphasis || md->cb.triple_emphasis) {
|
2811
2814
|
md->active_char['*'] = MD_CHAR_EMPHASIS;
|
2812
2815
|
md->active_char['_'] = MD_CHAR_EMPHASIS;
|
2816
|
+
|
2813
2817
|
if (extensions & MKDEXT_STRIKETHROUGH)
|
2814
2818
|
md->active_char['~'] = MD_CHAR_EMPHASIS;
|
2815
2819
|
if (extensions & MKDEXT_HIGHLIGHT)
|
2816
2820
|
md->active_char['='] = MD_CHAR_EMPHASIS;
|
2821
|
+
if (extensions & MKDEXT_QUOTE)
|
2822
|
+
md->active_char['"'] = MD_CHAR_QUOTE;
|
2817
2823
|
}
|
2818
2824
|
|
2819
2825
|
if (md->cb.codespan)
|
@@ -2838,9 +2844,6 @@ sd_markdown_new(
|
|
2838
2844
|
if (extensions & MKDEXT_SUPERSCRIPT)
|
2839
2845
|
md->active_char['^'] = MD_CHAR_SUPERSCRIPT;
|
2840
2846
|
|
2841
|
-
if (extensions & MKDEXT_QUOTE)
|
2842
|
-
md->active_char['"'] = MD_CHAR_QUOTE;
|
2843
|
-
|
2844
2847
|
/* Extension data */
|
2845
2848
|
md->ext_flags = extensions;
|
2846
2849
|
md->opaque = opaque;
|
@@ -2858,6 +2861,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
|
|
2858
2861
|
|
2859
2862
|
struct buf *text;
|
2860
2863
|
size_t beg, end;
|
2864
|
+
int in_fence = 0;
|
2861
2865
|
|
2862
2866
|
text = bufnew(64);
|
2863
2867
|
if (!text)
|
@@ -2869,7 +2873,8 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
|
|
2869
2873
|
/* reset the references table */
|
2870
2874
|
memset(&md->refs, 0x0, REF_TABLE_SIZE * sizeof(void *));
|
2871
2875
|
|
2872
|
-
int footnotes_enabled
|
2876
|
+
int footnotes_enabled = md->ext_flags & MKDEXT_FOOTNOTES;
|
2877
|
+
int codefences_enabled = md->ext_flags & MKDEXT_FENCED_CODE;
|
2873
2878
|
|
2874
2879
|
/* reset the footnotes lists */
|
2875
2880
|
if (footnotes_enabled) {
|
@@ -2885,10 +2890,13 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
|
|
2885
2890
|
if (doc_size >= 3 && memcmp(document, UTF8_BOM, 3) == 0)
|
2886
2891
|
beg += 3;
|
2887
2892
|
|
2888
|
-
while (beg < doc_size) /* iterating over lines */
|
2889
|
-
if (
|
2893
|
+
while (beg < doc_size) { /* iterating over lines */
|
2894
|
+
if (codefences_enabled && (is_codefence(document + beg, doc_size - beg, NULL) != 0))
|
2895
|
+
in_fence = !in_fence;
|
2896
|
+
|
2897
|
+
if (!in_fence && footnotes_enabled && is_footnote(document, beg, doc_size, &end, &md->footnotes_found))
|
2890
2898
|
beg = end;
|
2891
|
-
else if (is_ref(document, beg, doc_size, &end, md->refs))
|
2899
|
+
else if (!in_fence && is_ref(document, beg, doc_size, &end, md->refs))
|
2892
2900
|
beg = end;
|
2893
2901
|
else { /* skipping to the next line */
|
2894
2902
|
end = beg;
|
@@ -2908,6 +2916,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
|
|
2908
2916
|
|
2909
2917
|
beg = end;
|
2910
2918
|
}
|
2919
|
+
}
|
2911
2920
|
|
2912
2921
|
/* pre-grow the output buffer to minimize allocations */
|
2913
2922
|
bufgrow(ob, MARKDOWN_GROW(text->size));
|
@@ -2918,7 +2927,7 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
|
|
2918
2927
|
|
2919
2928
|
if (text->size) {
|
2920
2929
|
/* adding a final newline if not already present */
|
2921
|
-
if (text->data[text->size - 1] != '\n' &&
|
2930
|
+
if (text->data[text->size - 1] != '\n' && text->data[text->size - 1] != '\r')
|
2922
2931
|
bufputc(text, '\n');
|
2923
2932
|
|
2924
2933
|
parse_block(ob, md, text->data, text->size);
|
@@ -2931,6 +2940,9 @@ sd_markdown_render(struct buf *ob, const uint8_t *document, size_t doc_size, str
|
|
2931
2940
|
if (md->cb.doc_footer)
|
2932
2941
|
md->cb.doc_footer(ob, md->opaque);
|
2933
2942
|
|
2943
|
+
/* Null-terminate the buffer */
|
2944
|
+
bufcstr(ob);
|
2945
|
+
|
2934
2946
|
/* clean-up */
|
2935
2947
|
bufrelease(text);
|
2936
2948
|
free_link_refs(md->refs);
|