greenmat 3.2.2.4 → 3.5.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/greenmat/html.h CHANGED
@@ -1,17 +1,23 @@
1
1
  /*
2
- * Copyright (c) 2011, Vicent Marti
2
+ * Copyright (c) 2015, Vicent Marti
3
3
  *
4
- * Permission to use, copy, modify, and distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
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
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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 nesting_level;
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 nesting_level);
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
-
@@ -1,6 +1,6 @@
1
- /* C code produced by gperf version 3.0.4 */
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 http://git.io/RN0ncw for the list of recognized elements */
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 = 67, duplicates = 0 */
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
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
98
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
99
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
100
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
101
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
102
- 55, 50, 45, 40, 35, 30, 68, 68, 68, 68,
103
- 68, 68, 68, 68, 68, 15, 10, 15, 15, 15,
104
- 0, 20, 10, 10, 5, 68, 68, 0, 20, 25,
105
- 0, 68, 68, 0, 25, 0, 15, 68, 68, 68,
106
- 68, 68, 68, 68, 68, 68, 68, 15, 10, 15,
107
- 15, 15, 0, 20, 10, 10, 5, 68, 68, 0,
108
- 20, 25, 0, 68, 68, 0, 25, 0, 15, 68,
109
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
110
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
111
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
112
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
113
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
114
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
115
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
116
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
117
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
118
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
119
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
120
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
121
- 68, 68, 68, 68, 68, 68, 68, 68, 68, 68,
122
- 68, 68, 68, 68, 68, 68, 68
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 = 41,
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 = 67
149
+ MAX_HASH_VALUE = 72
156
150
  };
157
151
 
158
152
  static const char * const wordlist[] =
159
153
  {
160
154
  "",
161
155
  "p",
162
- "ul",
163
- "pre",
156
+ "dl",
157
+ "del",
164
158
  "form",
165
- "style",
159
+ "",
166
160
  "footer",
167
- "section",
168
- "", "", "",
161
+ "details",
162
+ "div",
163
+ "", "",
169
164
  "figure",
170
- "hr",
165
+ "ul",
171
166
  "fieldset",
172
- "math",
167
+ "",
173
168
  "figcaption",
174
169
  "header",
175
- "dl",
176
- "del",
177
- "",
178
- "blockquote",
170
+ "ol",
171
+ "pre",
172
+ "math",
173
+ "video",
179
174
  "script",
180
- "article",
181
- "div",
175
+ "section",
176
+ "noscript",
182
177
  "",
183
- "video",
178
+ "blockquote",
184
179
  "hgroup",
185
- "ol",
186
- "noscript",
187
- "", "",
180
+ "hr",
181
+ "ins",
182
+ "",
183
+ "style",
184
+ "output",
185
+ "summary",
186
+ "nav",
187
+ "",
188
+ "audio",
188
189
  "canvas",
189
190
  "dd",
190
- "nav",
191
+ "h1",
191
192
  "abbr",
192
- "audio",
193
- "iframe",
194
- "address",
195
- "ins",
196
- "",
197
193
  "table",
198
- "",
199
- "h6",
194
+ "iframe",
195
+ "article",
200
196
  "", "",
201
197
  "aside",
202
- "output",
203
- "h5",
198
+ "",
199
+ "h6",
204
200
  "", "",
205
201
  "tfoot",
206
202
  "",
203
+ "h5",
204
+ "", "", "", "",
207
205
  "h4",
208
206
  "", "", "", "",
209
- "h3",
207
+ "address",
210
208
  "", "", "", "",
211
- "h2",
209
+ "h3",
212
210
  "", "", "", "",
213
- "h1"
211
+ "h2"
214
212
  };
215
213
 
216
214
  if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
217
215
  {
218
- register int key = hash_block_tag (str, len);
216
+ unsigned int key = hash_block_tag (str, len);
219
217
 
220
- if (key <= MAX_HASH_VALUE && key >= 0)
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) 2011, Vicent Marti
2
+ * Copyright (c) 2015, Vicent Marti
3
3
  *
4
- * Permission to use, copy, modify, and distribute this software for any
5
- * purpose with or without fee is hereby granted, provided that the above
6
- * copyright notice and this permission notice appear in all copies.
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
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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 "&apos;" 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, "&rsquo;");
@@ -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 (word_boundary(previous_char) && size >= 3) {
297
+ if (fraction_boundary(previous_char) && size >= 3) {
286
298
  if (text[0] == '1' && text[1] == '/' && text[2] == '2') {
287
- if (size == 3 || word_boundary(text[3])) {
299
+ if (size == 3 || fraction_boundary(text[3])) {
288
300
  BUFPUTSL(ob, "&frac12;");
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 || word_boundary(text[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, "&frac14;");
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 || word_boundary(text[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, "&frac34;");
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("&#39;", text+(i+1), 5) == 0) {
386
+ bufput(ob, "&rsquo;", 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
-
@@ -1,20 +1,24 @@
1
- /* markdown.c - generic markdown parser */
2
-
3
1
  /*
4
2
  * Copyright (c) 2009, Natacha Porté
5
- * Copyright (c) 2011, Vicent Marti
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
- * Permission to use, copy, modify, and distribute this software for any
8
- * purpose with or without fee is hereby granted, provided that the above
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" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
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 + i < size && _isalnum(data[i + 1]))
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] != '\'' && 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 ordered list item prefix */
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
- /* parse_blockquote • handles parsing of a regular paragraph */
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 < 3)
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 = md->ext_flags & MKDEXT_FOOTNOTES;
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 (footnotes_enabled && is_footnote(document, beg, doc_size, &end, &md->footnotes_found))
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' && text->data[text->size - 1] != '\r')
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);