commonmarker 0.17.7.1 → 0.18.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/README.md +19 -17
- data/commonmarker.gemspec +1 -1
- data/ext/commonmarker/arena.c +2 -2
- data/ext/commonmarker/autolink.h +3 -3
- data/ext/commonmarker/blocks.c +21 -15
- data/ext/commonmarker/buffer.h +23 -23
- data/ext/commonmarker/chunk.h +1 -1
- data/ext/commonmarker/cmark-gfm-core-extensions.h +28 -0
- data/ext/commonmarker/{cmark_extension_api.h → cmark-gfm-extension_api.h} +86 -69
- data/ext/commonmarker/cmark-gfm-extensions_export.h +42 -0
- data/ext/commonmarker/{cmark.h → cmark-gfm.h} +118 -96
- data/ext/commonmarker/cmark-gfm_export.h +42 -0
- data/ext/commonmarker/cmark-gfm_version.h +7 -0
- data/ext/commonmarker/cmark.c +3 -3
- data/ext/commonmarker/cmark_ctype.h +6 -6
- data/ext/commonmarker/commonmark.c +8 -4
- data/ext/commonmarker/commonmarker.c +33 -15
- data/ext/commonmarker/commonmarker.h +1 -1
- data/ext/commonmarker/core-extensions.c +2 -2
- data/ext/commonmarker/ext_scanners.h +1 -1
- data/ext/commonmarker/footnotes.c +1 -1
- data/ext/commonmarker/houdini.h +6 -6
- data/ext/commonmarker/houdini_href_e.c +2 -2
- data/ext/commonmarker/html.c +15 -7
- data/ext/commonmarker/inlines.c +36 -5
- data/ext/commonmarker/inlines.h +1 -1
- data/ext/commonmarker/iterator.c +1 -1
- data/ext/commonmarker/iterator.h +1 -1
- data/ext/commonmarker/latex.c +1 -1
- data/ext/commonmarker/linked_list.c +1 -1
- data/ext/commonmarker/man.c +1 -1
- data/ext/commonmarker/node.c +17 -3
- data/ext/commonmarker/node.h +4 -4
- data/ext/commonmarker/plugin.h +2 -2
- data/ext/commonmarker/references.c +1 -1
- data/ext/commonmarker/registry.c +1 -1
- data/ext/commonmarker/registry.h +4 -4
- data/ext/commonmarker/render.c +1 -1
- data/ext/commonmarker/scanners.c +10550 -18051
- data/ext/commonmarker/scanners.h +1 -1
- data/ext/commonmarker/strikethrough.c +13 -3
- data/ext/commonmarker/strikethrough.h +3 -3
- data/ext/commonmarker/syntax_extension.c +11 -1
- data/ext/commonmarker/syntax_extension.h +4 -2
- data/ext/commonmarker/table.c +88 -9
- data/ext/commonmarker/table.h +7 -3
- data/ext/commonmarker/tagfilter.h +3 -3
- data/ext/commonmarker/utf8.h +6 -6
- data/ext/commonmarker/xml.c +10 -3
- data/lib/commonmarker/config.rb +4 -1
- data/lib/commonmarker/node.rb +6 -4
- data/lib/commonmarker/renderer/html_renderer.rb +12 -12
- data/lib/commonmarker/version.rb +1 -1
- data/test/test_extensions.rb +52 -1
- data/test/test_footnotes.rb +1 -1
- data/test/test_options.rb +35 -0
- data/test/test_spec.rb +4 -4
- metadata +12 -10
- data/ext/commonmarker/cmark_export.h +0 -42
- data/ext/commonmarker/cmark_version.h +0 -8
- data/ext/commonmarker/cmarkextensions_export.h +0 -42
- data/ext/commonmarker/core-extensions.h +0 -25
data/ext/commonmarker/scanners.h
CHANGED
|
@@ -27,7 +27,8 @@ static cmark_node *match(cmark_syntax_extension *self, cmark_parser *parser,
|
|
|
27
27
|
res->start_line = res->end_line = cmark_inline_parser_get_line(inline_parser);
|
|
28
28
|
res->start_column = cmark_inline_parser_get_column(inline_parser) - delims;
|
|
29
29
|
|
|
30
|
-
if (left_flanking || right_flanking)
|
|
30
|
+
if ((left_flanking || right_flanking) &&
|
|
31
|
+
(delims == 2 || (!(parser->options & CMARK_OPT_STRIKETHROUGH_DOUBLE_TILDE) && delims == 1))) {
|
|
31
32
|
cmark_inline_parser_push_delimiter(inline_parser, character, left_flanking,
|
|
32
33
|
right_flanking, res);
|
|
33
34
|
}
|
|
@@ -45,12 +46,14 @@ static delimiter *insert(cmark_syntax_extension *self, cmark_parser *parser,
|
|
|
45
46
|
|
|
46
47
|
strikethrough = opener->inl_text;
|
|
47
48
|
|
|
49
|
+
if (opener->inl_text->as.literal.len != closer->inl_text->as.literal.len)
|
|
50
|
+
goto done;
|
|
51
|
+
|
|
48
52
|
if (!cmark_node_set_type(strikethrough, CMARK_NODE_STRIKETHROUGH))
|
|
49
53
|
goto done;
|
|
50
54
|
|
|
51
55
|
cmark_node_set_syntax_extension(strikethrough, self);
|
|
52
56
|
|
|
53
|
-
cmark_node_set_string_content(strikethrough, "~");
|
|
54
57
|
tmp = cmark_node_next(opener->inl_text);
|
|
55
58
|
|
|
56
59
|
while (tmp) {
|
|
@@ -93,7 +96,7 @@ static int can_contain(cmark_syntax_extension *extension, cmark_node *node,
|
|
|
93
96
|
static void commonmark_render(cmark_syntax_extension *extension,
|
|
94
97
|
cmark_renderer *renderer, cmark_node *node,
|
|
95
98
|
cmark_event_type ev_type, int options) {
|
|
96
|
-
renderer->out(renderer, node,
|
|
99
|
+
renderer->out(renderer, node, "~~", false, LITERAL);
|
|
97
100
|
}
|
|
98
101
|
|
|
99
102
|
static void latex_render(cmark_syntax_extension *extension,
|
|
@@ -132,6 +135,12 @@ static void html_render(cmark_syntax_extension *extension,
|
|
|
132
135
|
}
|
|
133
136
|
}
|
|
134
137
|
|
|
138
|
+
static void plaintext_render(cmark_syntax_extension *extension,
|
|
139
|
+
cmark_renderer *renderer, cmark_node *node,
|
|
140
|
+
cmark_event_type ev_type, int options) {
|
|
141
|
+
renderer->out(renderer, node, "~", false, LITERAL);
|
|
142
|
+
}
|
|
143
|
+
|
|
135
144
|
cmark_syntax_extension *create_strikethrough_extension(void) {
|
|
136
145
|
cmark_syntax_extension *ext = cmark_syntax_extension_new("strikethrough");
|
|
137
146
|
cmark_llist *special_chars = NULL;
|
|
@@ -142,6 +151,7 @@ cmark_syntax_extension *create_strikethrough_extension(void) {
|
|
|
142
151
|
cmark_syntax_extension_set_latex_render_func(ext, latex_render);
|
|
143
152
|
cmark_syntax_extension_set_man_render_func(ext, man_render);
|
|
144
153
|
cmark_syntax_extension_set_html_render_func(ext, html_render);
|
|
154
|
+
cmark_syntax_extension_set_plaintext_render_func(ext, plaintext_render);
|
|
145
155
|
CMARK_NODE_STRIKETHROUGH = cmark_syntax_extension_add_node(1);
|
|
146
156
|
|
|
147
157
|
cmark_syntax_extension_set_match_inline_func(ext, match);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
#ifndef
|
|
2
|
-
#define
|
|
1
|
+
#ifndef CMARK_GFM_STRIKETHROUGH_H
|
|
2
|
+
#define CMARK_GFM_STRIKETHROUGH_H
|
|
3
3
|
|
|
4
|
-
#include "core-extensions.h"
|
|
4
|
+
#include "cmark-gfm-core-extensions.h"
|
|
5
5
|
|
|
6
6
|
extern cmark_node_type CMARK_NODE_STRIKETHROUGH;
|
|
7
7
|
cmark_syntax_extension *create_strikethrough_extension(void);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#include <stdlib.h>
|
|
2
2
|
#include <assert.h>
|
|
3
3
|
|
|
4
|
-
#include "cmark.h"
|
|
4
|
+
#include "cmark-gfm.h"
|
|
5
5
|
#include "syntax_extension.h"
|
|
6
6
|
#include "buffer.h"
|
|
7
7
|
|
|
@@ -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;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#ifndef CMARK_SYNTAX_EXTENSION_H
|
|
2
2
|
#define CMARK_SYNTAX_EXTENSION_H
|
|
3
3
|
|
|
4
|
-
#include "cmark.h"
|
|
5
|
-
#include "
|
|
4
|
+
#include "cmark-gfm.h"
|
|
5
|
+
#include "cmark-gfm-extension_api.h"
|
|
6
6
|
#include "config.h"
|
|
7
7
|
|
|
8
8
|
struct cmark_syntax_extension {
|
|
@@ -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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#include <
|
|
1
|
+
#include <cmark-gfm-extension_api.h>
|
|
2
2
|
#include <html.h>
|
|
3
3
|
#include <inlines.h>
|
|
4
4
|
#include <parser.h>
|
|
@@ -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;
|
|
@@ -380,7 +381,8 @@ static int can_contain(cmark_syntax_extension *extension, cmark_node *node,
|
|
|
380
381
|
child_type == CMARK_NODE_EMPH || child_type == CMARK_NODE_STRONG ||
|
|
381
382
|
child_type == CMARK_NODE_LINK || child_type == CMARK_NODE_IMAGE ||
|
|
382
383
|
child_type == CMARK_NODE_STRIKETHROUGH ||
|
|
383
|
-
child_type == CMARK_NODE_HTML_INLINE
|
|
384
|
+
child_type == CMARK_NODE_HTML_INLINE ||
|
|
385
|
+
child_type == CMARK_NODE_FOOTNOTE_REFERENCE;
|
|
384
386
|
}
|
|
385
387
|
return false;
|
|
386
388
|
}
|
|
@@ -487,6 +489,27 @@ static void latex_render(cmark_syntax_extension *extension,
|
|
|
487
489
|
}
|
|
488
490
|
}
|
|
489
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
|
+
|
|
490
513
|
static void man_render(cmark_syntax_extension *extension,
|
|
491
514
|
cmark_renderer *renderer, cmark_node *node,
|
|
492
515
|
cmark_event_type ev_type, int options) {
|
|
@@ -542,6 +565,18 @@ static void man_render(cmark_syntax_extension *extension,
|
|
|
542
565
|
}
|
|
543
566
|
}
|
|
544
567
|
|
|
568
|
+
static void html_table_add_align(cmark_strbuf* html, const char* align, int options) {
|
|
569
|
+
if (options & CMARK_OPT_TABLE_PREFER_STYLE_ATTRIBUTES) {
|
|
570
|
+
cmark_strbuf_puts(html, " style=\"text-align: ");
|
|
571
|
+
cmark_strbuf_puts(html, align);
|
|
572
|
+
cmark_strbuf_puts(html, "\"");
|
|
573
|
+
} else {
|
|
574
|
+
cmark_strbuf_puts(html, " align=\"");
|
|
575
|
+
cmark_strbuf_puts(html, align);
|
|
576
|
+
cmark_strbuf_puts(html, "\"");
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
545
580
|
struct html_table_state {
|
|
546
581
|
unsigned need_closing_table_body : 1;
|
|
547
582
|
unsigned in_table_header : 1;
|
|
@@ -566,10 +601,15 @@ static void html_render(cmark_syntax_extension *extension,
|
|
|
566
601
|
cmark_strbuf_putc(html, '>');
|
|
567
602
|
table_state->need_closing_table_body = false;
|
|
568
603
|
} else {
|
|
569
|
-
if (table_state->need_closing_table_body)
|
|
604
|
+
if (table_state->need_closing_table_body) {
|
|
605
|
+
cmark_html_render_cr(html);
|
|
570
606
|
cmark_strbuf_puts(html, "</tbody>");
|
|
607
|
+
cmark_html_render_cr(html);
|
|
608
|
+
}
|
|
571
609
|
table_state->need_closing_table_body = false;
|
|
572
|
-
|
|
610
|
+
cmark_html_render_cr(html);
|
|
611
|
+
cmark_strbuf_puts(html, "</table>");
|
|
612
|
+
cmark_html_render_cr(html);
|
|
573
613
|
}
|
|
574
614
|
} else if (node->type == CMARK_NODE_TABLE_ROW) {
|
|
575
615
|
if (entering) {
|
|
@@ -611,9 +651,9 @@ static void html_render(cmark_syntax_extension *extension,
|
|
|
611
651
|
break;
|
|
612
652
|
|
|
613
653
|
switch (alignments[i]) {
|
|
614
|
-
case 'l':
|
|
615
|
-
case 'c':
|
|
616
|
-
case 'r':
|
|
654
|
+
case 'l': html_table_add_align(html, "left", options); break;
|
|
655
|
+
case 'c': html_table_add_align(html, "center", options); break;
|
|
656
|
+
case 'r': html_table_add_align(html, "right", options); break;
|
|
617
657
|
}
|
|
618
658
|
|
|
619
659
|
cmark_html_render_sourcepos(node, html, options);
|
|
@@ -630,6 +670,16 @@ static void html_render(cmark_syntax_extension *extension,
|
|
|
630
670
|
}
|
|
631
671
|
}
|
|
632
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
|
+
|
|
633
683
|
static void opaque_free(cmark_syntax_extension *self, cmark_mem *mem, cmark_node *node) {
|
|
634
684
|
if (node->type == CMARK_NODE_TABLE) {
|
|
635
685
|
free_node_table(mem, node->as.opaque);
|
|
@@ -657,8 +707,10 @@ cmark_syntax_extension *create_table_extension(void) {
|
|
|
657
707
|
cmark_syntax_extension_set_commonmark_render_func(self, commonmark_render);
|
|
658
708
|
cmark_syntax_extension_set_plaintext_render_func(self, commonmark_render);
|
|
659
709
|
cmark_syntax_extension_set_latex_render_func(self, latex_render);
|
|
710
|
+
cmark_syntax_extension_set_xml_attr_func(self, xml_attr);
|
|
660
711
|
cmark_syntax_extension_set_man_render_func(self, man_render);
|
|
661
712
|
cmark_syntax_extension_set_html_render_func(self, html_render);
|
|
713
|
+
cmark_syntax_extension_set_opaque_alloc_func(self, opaque_alloc);
|
|
662
714
|
cmark_syntax_extension_set_opaque_free_func(self, opaque_free);
|
|
663
715
|
cmark_syntax_extension_set_commonmark_escape_func(self, escape);
|
|
664
716
|
CMARK_NODE_TABLE = cmark_syntax_extension_add_node(0);
|
|
@@ -668,16 +720,43 @@ cmark_syntax_extension *create_table_extension(void) {
|
|
|
668
720
|
return self;
|
|
669
721
|
}
|
|
670
722
|
|
|
671
|
-
uint16_t
|
|
723
|
+
uint16_t cmark_gfm_extensions_get_table_columns(cmark_node *node) {
|
|
672
724
|
if (node->type != CMARK_NODE_TABLE)
|
|
673
725
|
return 0;
|
|
674
726
|
|
|
675
727
|
return ((node_table *)node->as.opaque)->n_columns;
|
|
676
728
|
}
|
|
677
729
|
|
|
678
|
-
uint8_t *
|
|
730
|
+
uint8_t *cmark_gfm_extensions_get_table_alignments(cmark_node *node) {
|
|
679
731
|
if (node->type != CMARK_NODE_TABLE)
|
|
680
732
|
return 0;
|
|
681
733
|
|
|
682
734
|
return ((node_table *)node->as.opaque)->alignments;
|
|
683
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/table.h
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
#ifndef
|
|
2
|
-
#define
|
|
1
|
+
#ifndef CMARK_GFM_TABLE_H
|
|
2
|
+
#define CMARK_GFM_TABLE_H
|
|
3
3
|
|
|
4
|
-
#include "core-extensions.h"
|
|
4
|
+
#include "cmark-gfm-core-extensions.h"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
extern cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,
|
|
8
|
+
CMARK_NODE_TABLE_CELL;
|
|
5
9
|
|
|
6
10
|
cmark_syntax_extension *create_table_extension(void);
|
|
7
11
|
|
data/ext/commonmarker/utf8.h
CHANGED
|
@@ -8,24 +8,24 @@
|
|
|
8
8
|
extern "C" {
|
|
9
9
|
#endif
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
CMARK_GFM_EXPORT
|
|
12
12
|
void cmark_utf8proc_case_fold(cmark_strbuf *dest, const uint8_t *str,
|
|
13
13
|
bufsize_t len);
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
CMARK_GFM_EXPORT
|
|
16
16
|
void cmark_utf8proc_encode_char(int32_t uc, cmark_strbuf *buf);
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
CMARK_GFM_EXPORT
|
|
19
19
|
int cmark_utf8proc_iterate(const uint8_t *str, bufsize_t str_len, int32_t *dst);
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
CMARK_GFM_EXPORT
|
|
22
22
|
void cmark_utf8proc_check(cmark_strbuf *dest, const uint8_t *line,
|
|
23
23
|
bufsize_t size);
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
CMARK_GFM_EXPORT
|
|
26
26
|
int cmark_utf8proc_is_space(int32_t uc);
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
CMARK_GFM_EXPORT
|
|
29
29
|
int cmark_utf8proc_is_punctuation(int32_t uc);
|
|
30
30
|
|
|
31
31
|
#ifdef __cplusplus
|
data/ext/commonmarker/xml.c
CHANGED
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
#include <assert.h>
|
|
5
5
|
|
|
6
6
|
#include "config.h"
|
|
7
|
-
#include "cmark.h"
|
|
7
|
+
#include "cmark-gfm.h"
|
|
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
|
@@ -10,6 +10,7 @@ module CommonMarker
|
|
|
10
10
|
define :SMART, (1 << 10)
|
|
11
11
|
define :LIBERAL_HTML_TAG, (1 << 12)
|
|
12
12
|
define :FOOTNOTES, (1 << 13)
|
|
13
|
+
define :STRIKETHROUGH_DOUBLE_TILDE, (1 << 14)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
class Render
|
|
@@ -18,9 +19,11 @@ module CommonMarker
|
|
|
18
19
|
define :DEFAULT, 0
|
|
19
20
|
define :SOURCEPOS, (1 << 1)
|
|
20
21
|
define :HARDBREAKS, (1 << 2)
|
|
21
|
-
define :
|
|
22
|
+
define :UNSAFE, (1 << 17)
|
|
22
23
|
define :NOBREAKS, (1 << 4)
|
|
23
24
|
define :GITHUB_PRE_LANG, (1 << 11)
|
|
25
|
+
define :TABLE_PREFER_STYLE_ATTRIBUTES, (1 << 15)
|
|
26
|
+
define :FULL_INFO_STRING, (1 << 16)
|
|
24
27
|
end
|
|
25
28
|
|
|
26
29
|
def self.process_options(option, type)
|
data/lib/commonmarker/node.rb
CHANGED
|
@@ -31,21 +31,23 @@ module CommonMarker
|
|
|
31
31
|
# Public: Convert the node to a CommonMark string.
|
|
32
32
|
#
|
|
33
33
|
# options - A {Symbol} or {Array of Symbol}s indicating the render options
|
|
34
|
+
# width - Column to wrap the output at
|
|
34
35
|
#
|
|
35
36
|
# Returns a {String}.
|
|
36
|
-
def to_commonmark(options = :DEFAULT)
|
|
37
|
+
def to_commonmark(options = :DEFAULT, width = 120)
|
|
37
38
|
opts = Config.process_options(options, :render)
|
|
38
|
-
_render_commonmark(opts).force_encoding('utf-8')
|
|
39
|
+
_render_commonmark(opts, width).force_encoding('utf-8')
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
# Public: Convert the node to a plain text string.
|
|
42
43
|
#
|
|
43
44
|
# options - A {Symbol} or {Array of Symbol}s indicating the render options
|
|
45
|
+
# width - Column to wrap the output at
|
|
44
46
|
#
|
|
45
47
|
# Returns a {String}.
|
|
46
|
-
def to_plaintext(options = :DEFAULT)
|
|
48
|
+
def to_plaintext(options = :DEFAULT, width = 120)
|
|
47
49
|
opts = Config.process_options(options, :render)
|
|
48
|
-
_render_plaintext(opts).force_encoding('utf-8')
|
|
50
|
+
_render_plaintext(opts, width).force_encoding('utf-8')
|
|
49
51
|
end
|
|
50
52
|
|
|
51
53
|
# Public: Iterate over the children (if any) of the current pointer.
|
|
@@ -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
|
|
|
@@ -174,7 +174,7 @@ module CommonMarker
|
|
|
174
174
|
@alignments = node.table_alignments
|
|
175
175
|
@needs_close_tbody = false
|
|
176
176
|
out("<table#{sourcepos(node)}>\n", :children)
|
|
177
|
-
out("</tbody
|
|
177
|
+
out("</tbody>\n") if @needs_close_tbody
|
|
178
178
|
out("</table>\n")
|
|
179
179
|
end
|
|
180
180
|
|
|
@@ -182,7 +182,7 @@ module CommonMarker
|
|
|
182
182
|
@column_index = 0
|
|
183
183
|
|
|
184
184
|
@in_header = true
|
|
185
|
-
out("<thead>\n<tr#{sourcepos(node)}
|
|
185
|
+
out("<thead>\n<tr#{sourcepos(node)}>\n", :children, "</tr>\n</thead>\n")
|
|
186
186
|
@in_header = false
|
|
187
187
|
end
|
|
188
188
|
|
|
@@ -190,9 +190,9 @@ module CommonMarker
|
|
|
190
190
|
@column_index = 0
|
|
191
191
|
if !@in_header && !@needs_close_tbody
|
|
192
192
|
@needs_close_tbody = true
|
|
193
|
-
out("
|
|
193
|
+
out("<tbody>\n")
|
|
194
194
|
end
|
|
195
|
-
out("
|
|
195
|
+
out("<tr#{sourcepos(node)}>\n", :children, "</tr>\n")
|
|
196
196
|
end
|
|
197
197
|
|
|
198
198
|
def table_cell(node)
|
|
@@ -202,7 +202,7 @@ module CommonMarker
|
|
|
202
202
|
when :center; ' align="center"'
|
|
203
203
|
else; ''
|
|
204
204
|
end
|
|
205
|
-
out(@in_header ? "
|
|
205
|
+
out(@in_header ? "<th#{align}#{sourcepos(node)}>" : "<td#{align}#{sourcepos(node)}>", :children, @in_header ? "</th>\n" : "</td>\n")
|
|
206
206
|
@column_index += 1
|
|
207
207
|
end
|
|
208
208
|
|
|
@@ -211,7 +211,7 @@ module CommonMarker
|
|
|
211
211
|
end
|
|
212
212
|
|
|
213
213
|
def footnote_reference(node)
|
|
214
|
-
out("<sup class=\"footnote-ref\"><a href=\"#fn#{node.string_content}\" id=\"fnref#{node.string_content}\"
|
|
214
|
+
out("<sup class=\"footnote-ref\"><a href=\"#fn#{node.string_content}\" id=\"fnref#{node.string_content}\">#{node.string_content}</a></sup>")
|
|
215
215
|
end
|
|
216
216
|
|
|
217
217
|
def footnote_definition(_)
|
data/lib/commonmarker/version.rb
CHANGED
data/test/test_extensions.rb
CHANGED
|
@@ -35,6 +35,9 @@ Another extension:
|
|
|
35
35
|
assert out.include?("<del>hi</del>")
|
|
36
36
|
end
|
|
37
37
|
|
|
38
|
+
doc = CommonMarker.render_doc("~a~ ~~b~~ ~~~c~~~", :STRIKETHROUGH_DOUBLE_TILDE, [:strikethrough])
|
|
39
|
+
assert_equal doc.to_html, "<p>~a~ <del>b</del> ~~~c~~~</p>\n"
|
|
40
|
+
|
|
38
41
|
CommonMarker.render_html(@markdown, :DEFAULT, %i[table strikethrough]).tap do |out|
|
|
39
42
|
refute out.include?("| a")
|
|
40
43
|
refute out.include?("| <strong>x</strong>")
|
|
@@ -57,6 +60,9 @@ Another extension:
|
|
|
57
60
|
%w(<table> <tr> <th> a </th> <td> c </td> <strong>x</strong>).each {|html| assert out.include?(html) }
|
|
58
61
|
assert out.include?("~~hi~~")
|
|
59
62
|
end
|
|
63
|
+
|
|
64
|
+
doc = CommonMarker.render_doc("~a~ ~~b~~ ~~~c~~~", :STRIKETHROUGH_DOUBLE_TILDE, [:strikethrough])
|
|
65
|
+
assert_equal HtmlRenderer.new.render(doc), "<p>~a~ <del>b</del> ~~~c~~~</p>\n"
|
|
60
66
|
end
|
|
61
67
|
|
|
62
68
|
def test_bad_extension_specifications
|
|
@@ -67,6 +73,51 @@ Another extension:
|
|
|
67
73
|
|
|
68
74
|
def test_comments_are_kept_as_expected
|
|
69
75
|
assert_equal "<!--hello--> <blah> <xmp>\n",
|
|
70
|
-
CommonMarker.render_html("<!--hello--> <blah> <xmp>\n", :
|
|
76
|
+
CommonMarker.render_html("<!--hello--> <blah> <xmp>\n", :UNSAFE, %i[tagfilter])
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_table_prefer_style_attributes
|
|
80
|
+
assert_equal(<<-HTML, CommonMarker.render_html(<<-MD, :TABLE_PREFER_STYLE_ATTRIBUTES, %i[table]))
|
|
81
|
+
<table>
|
|
82
|
+
<thead>
|
|
83
|
+
<tr>
|
|
84
|
+
<th style="text-align: left">aaa</th>
|
|
85
|
+
<th>bbb</th>
|
|
86
|
+
<th style="text-align: center">ccc</th>
|
|
87
|
+
<th>ddd</th>
|
|
88
|
+
<th style="text-align: right">eee</th>
|
|
89
|
+
</tr>
|
|
90
|
+
</thead>
|
|
91
|
+
<tbody>
|
|
92
|
+
<tr>
|
|
93
|
+
<td style="text-align: left">fff</td>
|
|
94
|
+
<td>ggg</td>
|
|
95
|
+
<td style="text-align: center">hhh</td>
|
|
96
|
+
<td>iii</td>
|
|
97
|
+
<td style="text-align: right">jjj</td>
|
|
98
|
+
</tr>
|
|
99
|
+
</tbody>
|
|
100
|
+
</table>
|
|
101
|
+
HTML
|
|
102
|
+
aaa | bbb | ccc | ddd | eee
|
|
103
|
+
:-- | --- | :-: | --- | --:
|
|
104
|
+
fff | ggg | hhh | iii | jjj
|
|
105
|
+
MD
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def test_plaintext
|
|
109
|
+
assert_equal(<<-HTML, CommonMarker.render_doc(<<-MD, :DEFAULT, %i[table strikethrough]).to_plaintext)
|
|
110
|
+
Hello ~there~.
|
|
111
|
+
|
|
112
|
+
| a |
|
|
113
|
+
| --- |
|
|
114
|
+
| b |
|
|
115
|
+
HTML
|
|
116
|
+
Hello ~~there~~.
|
|
117
|
+
|
|
118
|
+
| a |
|
|
119
|
+
| - |
|
|
120
|
+
| b |
|
|
121
|
+
MD
|
|
71
122
|
end
|
|
72
123
|
end
|
data/test/test_footnotes.rb
CHANGED
|
@@ -4,7 +4,7 @@ class TestFootnotes < Minitest::Test
|
|
|
4
4
|
def setup
|
|
5
5
|
@doc = CommonMarker.render_doc("Hello[^hi].\n\n[^hi]: Hey!\n", :FOOTNOTES)
|
|
6
6
|
@expected = <<-HTML
|
|
7
|
-
<p>Hello<sup class="footnote-ref"><a href="#fn1" id="fnref1">
|
|
7
|
+
<p>Hello<sup class="footnote-ref"><a href="#fn1" id="fnref1">1</a></sup>.</p>
|
|
8
8
|
<section class="footnotes">
|
|
9
9
|
<ol>
|
|
10
10
|
<li id="fn1">
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class TestExtensions < Minitest::Test
|
|
4
|
+
def test_full_info_string
|
|
5
|
+
md = <<-MD
|
|
6
|
+
```ruby
|
|
7
|
+
module Foo
|
|
8
|
+
```
|
|
9
|
+
MD
|
|
10
|
+
|
|
11
|
+
CommonMarker.render_html(md, :FULL_INFO_STRING).tap do |out|
|
|
12
|
+
assert_includes out, %q(<pre><code class="language-ruby">)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
md = <<-MD
|
|
16
|
+
```ruby my info string
|
|
17
|
+
module Foo
|
|
18
|
+
```
|
|
19
|
+
MD
|
|
20
|
+
|
|
21
|
+
CommonMarker.render_html(md, :FULL_INFO_STRING).tap do |out|
|
|
22
|
+
assert_includes out, %q(<pre><code class="language-ruby" data-meta="my info string">)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
md = <<-MD
|
|
26
|
+
```ruby my \x00 string
|
|
27
|
+
module Foo
|
|
28
|
+
```
|
|
29
|
+
MD
|
|
30
|
+
|
|
31
|
+
CommonMarker.render_html(md, :FULL_INFO_STRING).tap do |out|
|
|
32
|
+
assert_includes out, %Q(<pre><code class="language-ruby" data-meta="my � string">)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|