commonmarker 0.17.13 → 0.18.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of commonmarker might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/ext/commonmarker/cmark-gfm-core-extensions.h +3 -0
- data/ext/commonmarker/cmark-gfm-extension_api.h +19 -2
- data/ext/commonmarker/cmark-gfm.h +16 -8
- data/ext/commonmarker/cmark-gfm_version.h +2 -2
- data/ext/commonmarker/commonmark.c +6 -2
- data/ext/commonmarker/html.c +4 -4
- data/ext/commonmarker/inlines.c +34 -3
- data/ext/commonmarker/node.c +17 -3
- data/ext/commonmarker/strikethrough.c +4 -1
- data/ext/commonmarker/syntax_extension.c +10 -0
- data/ext/commonmarker/syntax_extension.h +2 -0
- data/ext/commonmarker/table.c +61 -0
- data/ext/commonmarker/xml.c +9 -2
- data/lib/commonmarker/config.rb +1 -1
- data/lib/commonmarker/renderer/html_renderer.rb +6 -6
- data/lib/commonmarker/version.rb +1 -1
- data/test/test_extensions.rb +1 -1
- data/test/test_spec.rb +4 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11d4791ae4e26e529efbad366fef1bf1b0354caa
|
4
|
+
data.tar.gz: 67dec1b64e22464e2b5fce687171ae338a80221f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77749bbebb465097693ce23e1436f38cdc9995389d3527b5e52fe0f1ef37cafd4438416c2d60ebf7863d4d3713f580244fd7f0aa8c3f718d9f7ebb5baf20630d
|
7
|
+
data.tar.gz: 40ef8944199e42c68b7a61aa4d667778d555ad83502267b768e1d8c9424a8d9302e85ca68fe92c99b76fdf37d66afb05b093986792ed933973ac00a94bb20e0b
|
data/README.md
CHANGED
@@ -146,7 +146,7 @@ CommonMarker accepts the same options that CMark does, as symbols. Note that the
|
|
146
146
|
| `:GITHUB_PRE_LANG` | Use GitHub-style `<pre lang>` for fenced code blocks. |
|
147
147
|
| `:HARDBREAKS` | Treat `\n` as hardbreaks (by adding `<br/>`). |
|
148
148
|
| `:NOBREAKS` | Translate `\n` in the source to a single whitespace. |
|
149
|
-
| `:
|
149
|
+
| `:UNSAFE` | Allow raw HTML and unsafe links. |
|
150
150
|
| `:SOURCEPOS` | Include source position in rendered HTML. |
|
151
151
|
| `:TABLE_PREFER_STYLE_ATTRIBUTES` | Use `style` insted of `align` for table cells |
|
152
152
|
| `:FULL_INFO_STRING` | Include full info strings of code blocks in separate attribute |
|
@@ -177,7 +177,7 @@ The available extensions are:
|
|
177
177
|
* `:table` - This provides support for tables.
|
178
178
|
* `:strikethrough` - This provides support for strikethroughs.
|
179
179
|
* `:autolink` - This provides support for automatically converting URLs to anchor tags.
|
180
|
-
* `:tagfilter` - This
|
180
|
+
* `:tagfilter` - This escapes [several "unsafe" HTML tags](https://github.github.com/gfm/#disallowed-raw-html-extension-), causing them to not have any effect.
|
181
181
|
|
182
182
|
## Developing locally
|
183
183
|
|
@@ -18,6 +18,9 @@ uint16_t cmark_gfm_extensions_get_table_columns(cmark_node *node);
|
|
18
18
|
CMARK_GFM_EXTENSIONS_EXPORT
|
19
19
|
uint8_t *cmark_gfm_extensions_get_table_alignments(cmark_node *node);
|
20
20
|
|
21
|
+
CMARK_GFM_EXTENSIONS_EXPORT
|
22
|
+
int cmark_gfm_extensions_get_table_row_is_header(cmark_node *node);
|
23
|
+
|
21
24
|
#ifdef __cplusplus
|
22
25
|
}
|
23
26
|
#endif
|
@@ -106,8 +106,6 @@ typedef struct cmark_plugin cmark_plugin;
|
|
106
106
|
* with 'cmark_syntax_extension_set_private',
|
107
107
|
* and optionally define a free function for this data.
|
108
108
|
*/
|
109
|
-
typedef struct cmark_syntax_extension cmark_syntax_extension;
|
110
|
-
|
111
109
|
typedef struct subject cmark_inline_parser;
|
112
110
|
|
113
111
|
/** Exposed raw for now */
|
@@ -238,6 +236,9 @@ typedef int (*cmark_commonmark_escape_func) (cmark_syntax_extension *extension,
|
|
238
236
|
cmark_node *node,
|
239
237
|
int c);
|
240
238
|
|
239
|
+
typedef const char* (*cmark_xml_attr_func) (cmark_syntax_extension *extension,
|
240
|
+
cmark_node *node);
|
241
|
+
|
241
242
|
typedef void (*cmark_html_render_func) (cmark_syntax_extension *extension,
|
242
243
|
struct cmark_html_renderer *renderer,
|
243
244
|
cmark_node *node,
|
@@ -254,6 +255,10 @@ typedef cmark_node *(*cmark_postprocess_func) (cmark_syntax_extension *extension
|
|
254
255
|
|
255
256
|
typedef int (*cmark_ispunct_func) (char c);
|
256
257
|
|
258
|
+
typedef void (*cmark_opaque_alloc_func) (cmark_syntax_extension *extension,
|
259
|
+
cmark_mem *mem,
|
260
|
+
cmark_node *node);
|
261
|
+
|
257
262
|
typedef void (*cmark_opaque_free_func) (cmark_syntax_extension *extension,
|
258
263
|
cmark_mem *mem,
|
259
264
|
cmark_node *node);
|
@@ -343,6 +348,12 @@ void cmark_syntax_extension_set_latex_render_func(cmark_syntax_extension *extens
|
|
343
348
|
/** See the documentation for 'cmark_syntax_extension'
|
344
349
|
*/
|
345
350
|
CMARK_GFM_EXPORT
|
351
|
+
void cmark_syntax_extension_set_xml_attr_func(cmark_syntax_extension *extension,
|
352
|
+
cmark_xml_attr_func func);
|
353
|
+
|
354
|
+
/** See the documentation for 'cmark_syntax_extension'
|
355
|
+
*/
|
356
|
+
CMARK_GFM_EXPORT
|
346
357
|
void cmark_syntax_extension_set_man_render_func(cmark_syntax_extension *extension,
|
347
358
|
cmark_common_render_func func);
|
348
359
|
|
@@ -382,6 +393,12 @@ CMARK_GFM_EXPORT
|
|
382
393
|
void cmark_syntax_extension_set_postprocess_func(cmark_syntax_extension *extension,
|
383
394
|
cmark_postprocess_func func);
|
384
395
|
|
396
|
+
/** See the documentation for 'cmark_syntax_extension'
|
397
|
+
*/
|
398
|
+
CMARK_GFM_EXPORT
|
399
|
+
void cmark_syntax_extension_set_opaque_alloc_func(cmark_syntax_extension *extension,
|
400
|
+
cmark_opaque_alloc_func func);
|
401
|
+
|
385
402
|
/** See the documentation for 'cmark_syntax_extension'
|
386
403
|
*/
|
387
404
|
CMARK_GFM_EXPORT
|
@@ -92,6 +92,7 @@ typedef enum {
|
|
92
92
|
typedef struct cmark_node cmark_node;
|
93
93
|
typedef struct cmark_parser cmark_parser;
|
94
94
|
typedef struct cmark_iter cmark_iter;
|
95
|
+
typedef struct cmark_syntax_extension cmark_syntax_extension;
|
95
96
|
|
96
97
|
/**
|
97
98
|
* ## Custom memory allocator support
|
@@ -187,6 +188,13 @@ CMARK_GFM_EXPORT cmark_node *cmark_node_new(cmark_node_type type);
|
|
187
188
|
CMARK_GFM_EXPORT cmark_node *cmark_node_new_with_mem(cmark_node_type type,
|
188
189
|
cmark_mem *mem);
|
189
190
|
|
191
|
+
CMARK_GFM_EXPORT cmark_node *cmark_node_new_with_ext(cmark_node_type type,
|
192
|
+
cmark_syntax_extension *extension);
|
193
|
+
|
194
|
+
CMARK_GFM_EXPORT cmark_node *cmark_node_new_with_mem_and_ext(cmark_node_type type,
|
195
|
+
cmark_mem *mem,
|
196
|
+
cmark_syntax_extension *extension);
|
197
|
+
|
190
198
|
/** Frees the memory allocated for a node and any children.
|
191
199
|
*/
|
192
200
|
CMARK_GFM_EXPORT void cmark_node_free(cmark_node *node);
|
@@ -682,14 +690,6 @@ char *cmark_render_latex_with_mem(cmark_node *root, int options, int width, cmar
|
|
682
690
|
*/
|
683
691
|
#define CMARK_OPT_HARDBREAKS (1 << 2)
|
684
692
|
|
685
|
-
/** Suppress raw HTML and unsafe links (`javascript:`, `vbscript:`,
|
686
|
-
* `file:`, and `data:`, except for `image/png`, `image/gif`,
|
687
|
-
* `image/jpeg`, or `image/webp` mime types). Raw HTML is replaced
|
688
|
-
* by a placeholder HTML comment. Unsafe links are replaced by
|
689
|
-
* empty strings.
|
690
|
-
*/
|
691
|
-
#define CMARK_OPT_SAFE (1 << 3)
|
692
|
-
|
693
693
|
/** Render `softbreak` elements as spaces.
|
694
694
|
*/
|
695
695
|
#define CMARK_OPT_NOBREAKS (1 << 4)
|
@@ -738,6 +738,14 @@ char *cmark_render_latex_with_mem(cmark_node *root, int options, int width, cmar
|
|
738
738
|
*/
|
739
739
|
#define CMARK_OPT_FULL_INFO_STRING (1 << 16)
|
740
740
|
|
741
|
+
/** Allow raw HTML and unsafe links, `javascript:`, `vbscript:`, `file:`, and
|
742
|
+
* all `data:` URLs -- by default, only `image/png`, `image/gif`, `image/jpeg`,
|
743
|
+
* or `image/webp` mime types are allowed. Without this option, raw HTML is
|
744
|
+
* replaced by a placeholder HTML comment, and unsafe links are replaced by
|
745
|
+
* empty strings.
|
746
|
+
*/
|
747
|
+
#define CMARK_OPT_UNSAFE (1 << 17)
|
748
|
+
|
741
749
|
/**
|
742
750
|
* ## Version information
|
743
751
|
*/
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#ifndef CMARK_GFM_VERSION_H
|
2
2
|
#define CMARK_GFM_VERSION_H
|
3
3
|
|
4
|
-
#define CMARK_GFM_VERSION ((0 << 24) | (28 << 16) | (3 << 8) |
|
5
|
-
#define CMARK_GFM_VERSION_STRING "0.28.3.gfm.
|
4
|
+
#define CMARK_GFM_VERSION ((0 << 24) | (28 << 16) | (3 << 8) | 18)
|
5
|
+
#define CMARK_GFM_VERSION_STRING "0.28.3.gfm.18"
|
6
6
|
|
7
7
|
#endif
|
@@ -168,6 +168,7 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
168
168
|
int list_number;
|
169
169
|
cmark_delim_type list_delim;
|
170
170
|
int numticks;
|
171
|
+
bool extra_spaces;
|
171
172
|
int i;
|
172
173
|
bool entering = (ev_type == CMARK_EVENT_ENTER);
|
173
174
|
const char *info, *code, *title;
|
@@ -369,14 +370,17 @@ static int S_render_node(cmark_renderer *renderer, cmark_node *node,
|
|
369
370
|
code = cmark_node_get_literal(node);
|
370
371
|
code_len = strlen(code);
|
371
372
|
numticks = shortest_unused_backtick_sequence(code);
|
373
|
+
extra_spaces = code_len == 0 ||
|
374
|
+
code[0] == '`' || code[code_len - 1] == '`' ||
|
375
|
+
code[0] == ' ' || code[code_len - 1] == ' ';
|
372
376
|
for (i = 0; i < numticks; i++) {
|
373
377
|
LIT("`");
|
374
378
|
}
|
375
|
-
if (
|
379
|
+
if (extra_spaces) {
|
376
380
|
LIT(" ");
|
377
381
|
}
|
378
382
|
OUT(cmark_node_get_literal(node), allow_wrap, LITERAL);
|
379
|
-
if (
|
383
|
+
if (extra_spaces) {
|
380
384
|
LIT(" ");
|
381
385
|
}
|
382
386
|
for (i = 0; i < numticks; i++) {
|
data/ext/commonmarker/html.c
CHANGED
@@ -227,7 +227,7 @@ static int S_render_node(cmark_html_renderer *renderer, cmark_node *node,
|
|
227
227
|
|
228
228
|
case CMARK_NODE_HTML_BLOCK:
|
229
229
|
cmark_html_render_cr(html);
|
230
|
-
if (options &
|
230
|
+
if (!(options & CMARK_OPT_UNSAFE)) {
|
231
231
|
cmark_strbuf_puts(html, "<!-- raw HTML omitted -->");
|
232
232
|
} else if (renderer->filter_extensions) {
|
233
233
|
filter_html_block(renderer, node->as.literal.data, node->as.literal.len);
|
@@ -305,7 +305,7 @@ static int S_render_node(cmark_html_renderer *renderer, cmark_node *node,
|
|
305
305
|
break;
|
306
306
|
|
307
307
|
case CMARK_NODE_HTML_INLINE:
|
308
|
-
if (options &
|
308
|
+
if (!(options & CMARK_OPT_UNSAFE)) {
|
309
309
|
cmark_strbuf_puts(html, "<!-- raw HTML omitted -->");
|
310
310
|
} else {
|
311
311
|
filtered = false;
|
@@ -354,7 +354,7 @@ static int S_render_node(cmark_html_renderer *renderer, cmark_node *node,
|
|
354
354
|
case CMARK_NODE_LINK:
|
355
355
|
if (entering) {
|
356
356
|
cmark_strbuf_puts(html, "<a href=\"");
|
357
|
-
if (!((options &
|
357
|
+
if (!(!(options & CMARK_OPT_UNSAFE) &&
|
358
358
|
scan_dangerous_url(&node->as.link.url, 0))) {
|
359
359
|
houdini_escape_href(html, node->as.link.url.data,
|
360
360
|
node->as.link.url.len);
|
@@ -372,7 +372,7 @@ static int S_render_node(cmark_html_renderer *renderer, cmark_node *node,
|
|
372
372
|
case CMARK_NODE_IMAGE:
|
373
373
|
if (entering) {
|
374
374
|
cmark_strbuf_puts(html, "<img src=\"");
|
375
|
-
if (!((options &
|
375
|
+
if (!(!(options & CMARK_OPT_UNSAFE) &&
|
376
376
|
scan_dangerous_url(&node->as.link.url, 0))) {
|
377
377
|
houdini_escape_href(html, node->as.link.url.data,
|
378
378
|
node->as.link.url.len);
|
data/ext/commonmarker/inlines.c
CHANGED
@@ -321,6 +321,37 @@ static bufsize_t scan_to_closing_backticks(subject *subj,
|
|
321
321
|
return 0;
|
322
322
|
}
|
323
323
|
|
324
|
+
// Destructively modify string, converting newlines to
|
325
|
+
// spaces, then removing a single leading + trailing space.
|
326
|
+
static void S_normalize_code(cmark_strbuf *s) {
|
327
|
+
bufsize_t r, w;
|
328
|
+
|
329
|
+
for (r = 0, w = 0; r < s->size; ++r) {
|
330
|
+
switch (s->ptr[r]) {
|
331
|
+
case '\r':
|
332
|
+
if (s->ptr[r + 1] != '\n') {
|
333
|
+
s->ptr[w++] = ' ';
|
334
|
+
}
|
335
|
+
break;
|
336
|
+
case '\n':
|
337
|
+
s->ptr[w++] = ' ';
|
338
|
+
break;
|
339
|
+
default:
|
340
|
+
s->ptr[w++] = s->ptr[r];
|
341
|
+
}
|
342
|
+
}
|
343
|
+
|
344
|
+
// begins and ends with space?
|
345
|
+
if (s->ptr[0] == ' ' && s->ptr[w - 1] == ' ') {
|
346
|
+
cmark_strbuf_drop(s, 1);
|
347
|
+
cmark_strbuf_truncate(s, w - 2);
|
348
|
+
} else {
|
349
|
+
cmark_strbuf_truncate(s, w);
|
350
|
+
}
|
351
|
+
|
352
|
+
}
|
353
|
+
|
354
|
+
|
324
355
|
// Parse backtick code section or raw backticks, return an inline.
|
325
356
|
// Assumes that the subject has a backtick at the current position.
|
326
357
|
static cmark_node *handle_backticks(subject *subj, int options) {
|
@@ -336,8 +367,7 @@ static cmark_node *handle_backticks(subject *subj, int options) {
|
|
336
367
|
|
337
368
|
cmark_strbuf_set(&buf, subj->input.data + startpos,
|
338
369
|
endpos - startpos - openticks.len);
|
339
|
-
|
340
|
-
cmark_strbuf_normalize_whitespace(&buf);
|
370
|
+
S_normalize_code(&buf);
|
341
371
|
|
342
372
|
cmark_node *node = make_code(subj, startpos, endpos - openticks.len - 1, cmark_chunk_buf_detach(&buf));
|
343
373
|
adjust_subj_node_newlines(subj, node, endpos - startpos, openticks.len, options);
|
@@ -345,6 +375,7 @@ static cmark_node *handle_backticks(subject *subj, int options) {
|
|
345
375
|
}
|
346
376
|
}
|
347
377
|
|
378
|
+
|
348
379
|
// Scan ***, **, or * and return number scanned, or 0.
|
349
380
|
// Advances position.
|
350
381
|
static int scan_delims(subject *subj, unsigned char c, bool *can_open,
|
@@ -1410,7 +1441,7 @@ bufsize_t cmark_parse_reference_inline(cmark_mem *mem, cmark_chunk *input,
|
|
1410
1441
|
// parse optional link_title
|
1411
1442
|
beforetitle = subj.pos;
|
1412
1443
|
spnl(&subj);
|
1413
|
-
matchlen = scan_link_title(&subj.input, subj.pos);
|
1444
|
+
matchlen = subj.pos == beforetitle ? 0 : scan_link_title(&subj.input, subj.pos);
|
1414
1445
|
if (matchlen) {
|
1415
1446
|
title = cmark_chunk_dup(&subj.input, subj.pos, matchlen);
|
1416
1447
|
subj.pos += matchlen;
|
data/ext/commonmarker/node.c
CHANGED
@@ -69,10 +69,11 @@ static bool S_can_contain(cmark_node *node, cmark_node *child) {
|
|
69
69
|
return cmark_node_can_contain_type(node, (cmark_node_type) child->type);
|
70
70
|
}
|
71
71
|
|
72
|
-
cmark_node *
|
72
|
+
cmark_node *cmark_node_new_with_mem_and_ext(cmark_node_type type, cmark_mem *mem, cmark_syntax_extension *extension) {
|
73
73
|
cmark_node *node = (cmark_node *)mem->calloc(1, sizeof(*node));
|
74
74
|
cmark_strbuf_init(mem, &node->content, 0);
|
75
75
|
node->type = (uint16_t)type;
|
76
|
+
node->extension = extension;
|
76
77
|
|
77
78
|
switch (node->type) {
|
78
79
|
case CMARK_NODE_HEADING:
|
@@ -91,12 +92,25 @@ cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem) {
|
|
91
92
|
break;
|
92
93
|
}
|
93
94
|
|
95
|
+
if (node->extension && node->extension->opaque_alloc_func) {
|
96
|
+
node->extension->opaque_alloc_func(node->extension, mem, node);
|
97
|
+
}
|
98
|
+
|
94
99
|
return node;
|
95
100
|
}
|
96
101
|
|
97
|
-
cmark_node *
|
102
|
+
cmark_node *cmark_node_new_with_ext(cmark_node_type type, cmark_syntax_extension *extension) {
|
98
103
|
extern cmark_mem CMARK_DEFAULT_MEM_ALLOCATOR;
|
99
|
-
return
|
104
|
+
return cmark_node_new_with_mem_and_ext(type, &CMARK_DEFAULT_MEM_ALLOCATOR, extension);
|
105
|
+
}
|
106
|
+
|
107
|
+
cmark_node *cmark_node_new_with_mem(cmark_node_type type, cmark_mem *mem)
|
108
|
+
{
|
109
|
+
return cmark_node_new_with_mem_and_ext(type, mem, NULL);
|
110
|
+
}
|
111
|
+
|
112
|
+
cmark_node *cmark_node_new(cmark_node_type type) {
|
113
|
+
return cmark_node_new_with_ext(type, NULL);
|
100
114
|
}
|
101
115
|
|
102
116
|
static void free_node_as(cmark_node *node) {
|
@@ -28,7 +28,7 @@ static cmark_node *match(cmark_syntax_extension *self, cmark_parser *parser,
|
|
28
28
|
res->start_column = cmark_inline_parser_get_column(inline_parser) - delims;
|
29
29
|
|
30
30
|
if ((left_flanking || right_flanking) &&
|
31
|
-
(!(parser->options & CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE)
|
31
|
+
(delims == 2 || (!(parser->options & CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE) && delims == 1))) {
|
32
32
|
cmark_inline_parser_push_delimiter(inline_parser, character, left_flanking,
|
33
33
|
right_flanking, res);
|
34
34
|
}
|
@@ -46,6 +46,9 @@ static delimiter *insert(cmark_syntax_extension *self, cmark_parser *parser,
|
|
46
46
|
|
47
47
|
strikethrough = opener->inl_text;
|
48
48
|
|
49
|
+
if (opener->inl_text->as.literal.len != closer->inl_text->as.literal.len)
|
50
|
+
goto done;
|
51
|
+
|
49
52
|
if (!cmark_node_set_type(strikethrough, CMARK_NODE_STRIKETHROUGH))
|
50
53
|
goto done;
|
51
54
|
|
@@ -97,6 +97,11 @@ void cmark_syntax_extension_set_latex_render_func(cmark_syntax_extension *extens
|
|
97
97
|
extension->latex_render_func = func;
|
98
98
|
}
|
99
99
|
|
100
|
+
void cmark_syntax_extension_set_xml_attr_func(cmark_syntax_extension *extension,
|
101
|
+
cmark_xml_attr_func func) {
|
102
|
+
extension->xml_attr_func = func;
|
103
|
+
}
|
104
|
+
|
100
105
|
void cmark_syntax_extension_set_man_render_func(cmark_syntax_extension *extension,
|
101
106
|
cmark_common_render_func func) {
|
102
107
|
extension->man_render_func = func;
|
@@ -128,6 +133,11 @@ void *cmark_syntax_extension_get_private(cmark_syntax_extension *extension) {
|
|
128
133
|
return extension->priv;
|
129
134
|
}
|
130
135
|
|
136
|
+
void cmark_syntax_extension_set_opaque_alloc_func(cmark_syntax_extension *extension,
|
137
|
+
cmark_opaque_alloc_func func) {
|
138
|
+
extension->opaque_alloc_func = func;
|
139
|
+
}
|
140
|
+
|
131
141
|
void cmark_syntax_extension_set_opaque_free_func(cmark_syntax_extension *extension,
|
132
142
|
cmark_opaque_free_func func) {
|
133
143
|
extension->opaque_free_func = func;
|
@@ -21,10 +21,12 @@ struct cmark_syntax_extension {
|
|
21
21
|
cmark_common_render_func commonmark_render_func;
|
22
22
|
cmark_common_render_func plaintext_render_func;
|
23
23
|
cmark_common_render_func latex_render_func;
|
24
|
+
cmark_xml_attr_func xml_attr_func;
|
24
25
|
cmark_common_render_func man_render_func;
|
25
26
|
cmark_html_render_func html_render_func;
|
26
27
|
cmark_html_filter_func html_filter_func;
|
27
28
|
cmark_postprocess_func postprocess_func;
|
29
|
+
cmark_opaque_alloc_func opaque_alloc_func;
|
28
30
|
cmark_opaque_free_func opaque_free_func;
|
29
31
|
cmark_commonmark_escape_func commonmark_escape_func;
|
30
32
|
};
|
data/ext/commonmarker/table.c
CHANGED
@@ -9,6 +9,7 @@
|
|
9
9
|
#include "ext_scanners.h"
|
10
10
|
#include "strikethrough.h"
|
11
11
|
#include "table.h"
|
12
|
+
#include "cmark-gfm-core-extensions.h"
|
12
13
|
|
13
14
|
cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,
|
14
15
|
CMARK_NODE_TABLE_CELL;
|
@@ -488,6 +489,27 @@ static void latex_render(cmark_syntax_extension *extension,
|
|
488
489
|
}
|
489
490
|
}
|
490
491
|
|
492
|
+
static const char *xml_attr(cmark_syntax_extension *extension,
|
493
|
+
cmark_node *node) {
|
494
|
+
if (node->type == CMARK_NODE_TABLE_CELL) {
|
495
|
+
if (cmark_gfm_extensions_get_table_row_is_header(node->parent)) {
|
496
|
+
uint8_t *alignments = get_table_alignments(node->parent->parent);
|
497
|
+
int i = 0;
|
498
|
+
cmark_node *n;
|
499
|
+
for (n = node->parent->first_child; n; n = n->next, ++i)
|
500
|
+
if (n == node)
|
501
|
+
break;
|
502
|
+
switch (alignments[i]) {
|
503
|
+
case 'l': return " align=\"left\"";
|
504
|
+
case 'c': return " align=\"center\"";
|
505
|
+
case 'r': return " align=\"right\"";
|
506
|
+
}
|
507
|
+
}
|
508
|
+
}
|
509
|
+
|
510
|
+
return NULL;
|
511
|
+
}
|
512
|
+
|
491
513
|
static void man_render(cmark_syntax_extension *extension,
|
492
514
|
cmark_renderer *renderer, cmark_node *node,
|
493
515
|
cmark_event_type ev_type, int options) {
|
@@ -648,6 +670,16 @@ static void html_render(cmark_syntax_extension *extension,
|
|
648
670
|
}
|
649
671
|
}
|
650
672
|
|
673
|
+
static void opaque_alloc(cmark_syntax_extension *self, cmark_mem *mem, cmark_node *node) {
|
674
|
+
if (node->type == CMARK_NODE_TABLE) {
|
675
|
+
node->as.opaque = mem->calloc(1, sizeof(node_table));
|
676
|
+
} else if (node->type == CMARK_NODE_TABLE_ROW) {
|
677
|
+
node->as.opaque = mem->calloc(1, sizeof(node_table_row));
|
678
|
+
} else if (node->type == CMARK_NODE_TABLE_CELL) {
|
679
|
+
node->as.opaque = mem->calloc(1, sizeof(node_cell));
|
680
|
+
}
|
681
|
+
}
|
682
|
+
|
651
683
|
static void opaque_free(cmark_syntax_extension *self, cmark_mem *mem, cmark_node *node) {
|
652
684
|
if (node->type == CMARK_NODE_TABLE) {
|
653
685
|
free_node_table(mem, node->as.opaque);
|
@@ -675,8 +707,10 @@ cmark_syntax_extension *create_table_extension(void) {
|
|
675
707
|
cmark_syntax_extension_set_commonmark_render_func(self, commonmark_render);
|
676
708
|
cmark_syntax_extension_set_plaintext_render_func(self, commonmark_render);
|
677
709
|
cmark_syntax_extension_set_latex_render_func(self, latex_render);
|
710
|
+
cmark_syntax_extension_set_xml_attr_func(self, xml_attr);
|
678
711
|
cmark_syntax_extension_set_man_render_func(self, man_render);
|
679
712
|
cmark_syntax_extension_set_html_render_func(self, html_render);
|
713
|
+
cmark_syntax_extension_set_opaque_alloc_func(self, opaque_alloc);
|
680
714
|
cmark_syntax_extension_set_opaque_free_func(self, opaque_free);
|
681
715
|
cmark_syntax_extension_set_commonmark_escape_func(self, escape);
|
682
716
|
CMARK_NODE_TABLE = cmark_syntax_extension_add_node(0);
|
@@ -699,3 +733,30 @@ uint8_t *cmark_gfm_extensions_get_table_alignments(cmark_node *node) {
|
|
699
733
|
|
700
734
|
return ((node_table *)node->as.opaque)->alignments;
|
701
735
|
}
|
736
|
+
|
737
|
+
int cmark_gfm_extensions_set_table_columns(cmark_node *node, uint16_t n_columns) {
|
738
|
+
return set_n_table_columns(node, n_columns);
|
739
|
+
}
|
740
|
+
|
741
|
+
int cmark_gfm_extensions_set_table_alignments(cmark_node *node, uint16_t ncols, uint8_t *alignments) {
|
742
|
+
uint8_t *a = (uint8_t *)cmark_node_mem(node)->calloc(1, ncols);
|
743
|
+
memcpy(a, alignments, ncols);
|
744
|
+
return set_table_alignments(node, a);
|
745
|
+
}
|
746
|
+
|
747
|
+
int cmark_gfm_extensions_get_table_row_is_header(cmark_node *node)
|
748
|
+
{
|
749
|
+
if (!node || node->type != CMARK_NODE_TABLE_ROW)
|
750
|
+
return 0;
|
751
|
+
|
752
|
+
return ((node_table_row *)node->as.opaque)->is_header;
|
753
|
+
}
|
754
|
+
|
755
|
+
int cmark_gfm_extensions_set_table_row_is_header(cmark_node *node, int is_header)
|
756
|
+
{
|
757
|
+
if (!node || node->type != CMARK_NODE_TABLE_ROW)
|
758
|
+
return 0;
|
759
|
+
|
760
|
+
((node_table_row *)node->as.opaque)->is_header = (is_header != 0);
|
761
|
+
return 1;
|
762
|
+
}
|
data/ext/commonmarker/xml.c
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
#include "node.h"
|
9
9
|
#include "buffer.h"
|
10
10
|
#include "houdini.h"
|
11
|
+
#include "syntax_extension.h"
|
11
12
|
|
12
13
|
#define BUFFER_SIZE 100
|
13
14
|
|
@@ -50,6 +51,12 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type,
|
|
50
51
|
cmark_strbuf_puts(xml, buffer);
|
51
52
|
}
|
52
53
|
|
54
|
+
if (node->extension && node->extension->xml_attr_func) {
|
55
|
+
const char* r = node->extension->xml_attr_func(node->extension, node);
|
56
|
+
if (r != NULL)
|
57
|
+
cmark_strbuf_puts(xml, r);
|
58
|
+
}
|
59
|
+
|
53
60
|
literal = false;
|
54
61
|
|
55
62
|
switch (node->type) {
|
@@ -60,7 +67,7 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type,
|
|
60
67
|
case CMARK_NODE_CODE:
|
61
68
|
case CMARK_NODE_HTML_BLOCK:
|
62
69
|
case CMARK_NODE_HTML_INLINE:
|
63
|
-
cmark_strbuf_puts(xml, ">");
|
70
|
+
cmark_strbuf_puts(xml, " xml:space=\"preserve\">");
|
64
71
|
escape_xml(xml, node->as.literal.data, node->as.literal.len);
|
65
72
|
cmark_strbuf_puts(xml, "</");
|
66
73
|
cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
|
@@ -100,7 +107,7 @@ static int S_render_node(cmark_node *node, cmark_event_type ev_type,
|
|
100
107
|
escape_xml(xml, node->as.code.info.data, node->as.code.info.len);
|
101
108
|
cmark_strbuf_putc(xml, '"');
|
102
109
|
}
|
103
|
-
cmark_strbuf_puts(xml, ">");
|
110
|
+
cmark_strbuf_puts(xml, " xml:space=\"preserve\">");
|
104
111
|
escape_xml(xml, node->as.code.literal.data, node->as.code.literal.len);
|
105
112
|
cmark_strbuf_puts(xml, "</");
|
106
113
|
cmark_strbuf_puts(xml, cmark_node_get_type_string(node));
|
data/lib/commonmarker/config.rb
CHANGED
@@ -19,7 +19,7 @@ module CommonMarker
|
|
19
19
|
define :DEFAULT, 0
|
20
20
|
define :SOURCEPOS, (1 << 1)
|
21
21
|
define :HARDBREAKS, (1 << 2)
|
22
|
-
define :
|
22
|
+
define :UNSAFE, (1 << 17)
|
23
23
|
define :NOBREAKS, (1 << 4)
|
24
24
|
define :GITHUB_PRE_LANG, (1 << 11)
|
25
25
|
define :TABLE_PREFER_STYLE_ATTRIBUTES, (1 << 15)
|
@@ -103,19 +103,19 @@ module CommonMarker
|
|
103
103
|
|
104
104
|
def html(node)
|
105
105
|
block do
|
106
|
-
if option_enabled?(:
|
107
|
-
out('<!-- raw HTML omitted -->')
|
108
|
-
else
|
106
|
+
if option_enabled?(:UNSAFE)
|
109
107
|
out(tagfilter(node.string_content))
|
108
|
+
else
|
109
|
+
out('<!-- raw HTML omitted -->')
|
110
110
|
end
|
111
111
|
end
|
112
112
|
end
|
113
113
|
|
114
114
|
def inline_html(node)
|
115
|
-
if option_enabled?(:
|
116
|
-
out('<!-- raw HTML omitted -->')
|
117
|
-
else
|
115
|
+
if option_enabled?(:UNSAFE)
|
118
116
|
out(tagfilter(node.string_content))
|
117
|
+
else
|
118
|
+
out('<!-- raw HTML omitted -->')
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
data/lib/commonmarker/version.rb
CHANGED
data/test/test_extensions.rb
CHANGED
@@ -73,7 +73,7 @@ Another extension:
|
|
73
73
|
|
74
74
|
def test_comments_are_kept_as_expected
|
75
75
|
assert_equal "<!--hello--> <blah> <xmp>\n",
|
76
|
-
CommonMarker.render_html("<!--hello--> <blah> <xmp>\n", :
|
76
|
+
CommonMarker.render_html("<!--hello--> <blah> <xmp>\n", :UNSAFE, %i[tagfilter])
|
77
77
|
end
|
78
78
|
|
79
79
|
def test_table_prefer_style_attributes
|
data/test/test_spec.rb
CHANGED
@@ -9,18 +9,18 @@ class TestSpec < Minitest::Test
|
|
9
9
|
doc = CommonMarker.render_doc(testcase[:markdown], :DEFAULT, testcase[:extensions])
|
10
10
|
|
11
11
|
define_method("test_to_html_example_#{testcase[:example]}") do
|
12
|
-
actual = doc.to_html(:
|
12
|
+
actual = doc.to_html(:UNSAFE, testcase[:extensions]).rstrip
|
13
13
|
assert_equal testcase[:html], actual, testcase[:markdown]
|
14
14
|
end
|
15
15
|
|
16
16
|
define_method("test_html_renderer_example_#{testcase[:example]}") do
|
17
|
-
actual = HtmlRenderer.new(extensions: testcase[:extensions]).render(doc).rstrip
|
17
|
+
actual = HtmlRenderer.new(options: :UNSAFE, extensions: testcase[:extensions]).render(doc).rstrip
|
18
18
|
assert_equal testcase[:html], actual, testcase[:markdown]
|
19
19
|
end
|
20
20
|
|
21
21
|
define_method("test_sourcepos_example_#{testcase[:example]}") do
|
22
|
-
lhs = doc.to_html(:SOURCEPOS, testcase[:extensions]).rstrip
|
23
|
-
rhs = HtmlRenderer.new(options: :SOURCEPOS, extensions: testcase[:extensions]).render(doc).rstrip
|
22
|
+
lhs = doc.to_html([:UNSAFE, :SOURCEPOS], testcase[:extensions]).rstrip
|
23
|
+
rhs = HtmlRenderer.new(options: [:UNSAFE, :SOURCEPOS], extensions: testcase[:extensions]).render(doc).rstrip
|
24
24
|
assert_equal lhs, rhs, testcase[:markdown]
|
25
25
|
end
|
26
26
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: commonmarker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Garen Torikian
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2018-
|
12
|
+
date: 2018-10-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ruby-enum
|
@@ -243,7 +243,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
243
243
|
version: '0'
|
244
244
|
requirements: []
|
245
245
|
rubyforge_project:
|
246
|
-
rubygems_version: 2.5.
|
246
|
+
rubygems_version: 2.5.2.3
|
247
247
|
signing_key:
|
248
248
|
specification_version: 4
|
249
249
|
summary: CommonMark parser and renderer. Written in C, wrapped in Ruby.
|