commonmarker 0.19.0 → 0.21.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of commonmarker might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/README.md +2 -3
- data/Rakefile +16 -4
- data/bin/commonmarker +82 -44
- data/commonmarker.gemspec +9 -12
- data/ext/commonmarker/blocks.c +89 -29
- data/ext/commonmarker/buffer.c +0 -1
- data/ext/commonmarker/chunk.h +0 -1
- data/ext/commonmarker/cmark-gfm-core-extensions.h +24 -1
- data/ext/commonmarker/cmark-gfm.h +14 -8
- data/ext/commonmarker/cmark-gfm_version.h +2 -2
- data/ext/commonmarker/commonmark.c +9 -4
- data/ext/commonmarker/commonmarker.c +120 -78
- data/ext/commonmarker/html.c +4 -4
- data/ext/commonmarker/inlines.c +21 -14
- data/ext/commonmarker/iterator.h +0 -1
- data/ext/commonmarker/map.h +0 -1
- data/ext/commonmarker/node.h +2 -0
- data/ext/commonmarker/parser.h +2 -1
- data/ext/commonmarker/render.c +16 -14
- data/ext/commonmarker/render.h +0 -1
- data/ext/commonmarker/scanners.c +777 -951
- data/ext/commonmarker/scanners.h +0 -2
- data/ext/commonmarker/table.c +52 -13
- data/ext/commonmarker/tasklist.c +34 -13
- data/lib/commonmarker.rb +5 -4
- data/lib/commonmarker/config.rb +5 -4
- data/lib/commonmarker/node.rb +1 -1
- data/lib/commonmarker/node/inspect.rb +12 -12
- data/lib/commonmarker/renderer.rb +7 -7
- data/lib/commonmarker/renderer/html_renderer.rb +22 -35
- data/lib/commonmarker/version.rb +1 -1
- data/test/benchmark.rb +1 -5
- data/test/fixtures/strong.md +1 -0
- data/test/fixtures/table.md +10 -0
- data/test/test_attributes.rb +3 -3
- data/test/test_commands.rb +31 -0
- data/test/test_commonmark.rb +11 -11
- data/test/test_encoding.rb +1 -2
- data/test/test_extensions.rb +40 -52
- data/test/test_footnotes.rb +9 -9
- data/test/test_gc.rb +2 -0
- data/test/test_helper.rb +15 -8
- data/test/test_maliciousness.rb +192 -190
- data/test/test_node.rb +10 -12
- data/test/test_options.rb +15 -15
- data/test/test_pathological_inputs.rb +2 -2
- data/test/test_plaintext.rb +21 -21
- data/test/test_renderer.rb +9 -9
- data/test/test_spec.rb +3 -2
- data/test/test_tasklists.rb +22 -6
- metadata +51 -46
data/ext/commonmarker/scanners.h
CHANGED
@@ -26,7 +26,6 @@ bufsize_t _scan_link_title(const unsigned char *p);
|
|
26
26
|
bufsize_t _scan_spacechars(const unsigned char *p);
|
27
27
|
bufsize_t _scan_atx_heading_start(const unsigned char *p);
|
28
28
|
bufsize_t _scan_setext_heading_line(const unsigned char *p);
|
29
|
-
bufsize_t _scan_thematic_break(const unsigned char *p);
|
30
29
|
bufsize_t _scan_open_code_fence(const unsigned char *p);
|
31
30
|
bufsize_t _scan_close_code_fence(const unsigned char *p);
|
32
31
|
bufsize_t _scan_entity(const unsigned char *p);
|
@@ -50,7 +49,6 @@ bufsize_t _scan_footnote_definition(const unsigned char *p);
|
|
50
49
|
#define scan_atx_heading_start(c, n) _scan_at(&_scan_atx_heading_start, c, n)
|
51
50
|
#define scan_setext_heading_line(c, n) \
|
52
51
|
_scan_at(&_scan_setext_heading_line, c, n)
|
53
|
-
#define scan_thematic_break(c, n) _scan_at(&_scan_thematic_break, c, n)
|
54
52
|
#define scan_open_code_fence(c, n) _scan_at(&_scan_open_code_fence, c, n)
|
55
53
|
#define scan_close_code_fence(c, n) _scan_at(&_scan_close_code_fence, c, n)
|
56
54
|
#define scan_entity(c, n) _scan_at(&_scan_entity, c, n)
|
data/ext/commonmarker/table.c
CHANGED
@@ -16,6 +16,7 @@ cmark_node_type CMARK_NODE_TABLE, CMARK_NODE_TABLE_ROW,
|
|
16
16
|
|
17
17
|
typedef struct {
|
18
18
|
uint16_t n_columns;
|
19
|
+
int paragraph_offset;
|
19
20
|
cmark_llist *cells;
|
20
21
|
} table_row;
|
21
22
|
|
@@ -115,6 +116,7 @@ static table_row *row_from_string(cmark_syntax_extension *self,
|
|
115
116
|
int len) {
|
116
117
|
table_row *row = NULL;
|
117
118
|
bufsize_t cell_matched = 1, pipe_matched = 1, offset;
|
119
|
+
int cell_end_offset;
|
118
120
|
|
119
121
|
row = (table_row *)parser->mem->calloc(1, sizeof(table_row));
|
120
122
|
row->n_columns = 0;
|
@@ -129,20 +131,32 @@ static table_row *row_from_string(cmark_syntax_extension *self,
|
|
129
131
|
pipe_matched = scan_table_cell_end(string, len, offset + cell_matched);
|
130
132
|
|
131
133
|
if (cell_matched || pipe_matched) {
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
134
|
+
cell_end_offset = offset + cell_matched - 1;
|
135
|
+
|
136
|
+
if (string[cell_end_offset] == '\n' || string[cell_end_offset] == '\r') {
|
137
|
+
row->paragraph_offset = cell_end_offset;
|
138
|
+
|
139
|
+
cmark_llist_free_full(parser->mem, row->cells, (cmark_free_func)free_table_cell);
|
140
|
+
row->cells = NULL;
|
141
|
+
row->n_columns = 0;
|
142
|
+
} else {
|
143
|
+
cmark_strbuf *cell_buf = unescape_pipes(parser->mem, string + offset,
|
144
|
+
cell_matched);
|
145
|
+
cmark_strbuf_trim(cell_buf);
|
146
|
+
|
147
|
+
node_cell *cell = (node_cell *)parser->mem->calloc(1, sizeof(*cell));
|
148
|
+
cell->buf = cell_buf;
|
149
|
+
cell->start_offset = offset;
|
150
|
+
cell->end_offset = cell_end_offset;
|
151
|
+
|
152
|
+
while (cell->start_offset > 0 && string[cell->start_offset - 1] != '|') {
|
153
|
+
--cell->start_offset;
|
154
|
+
++cell->internal_offset;
|
155
|
+
}
|
156
|
+
|
157
|
+
row->n_columns += 1;
|
158
|
+
row->cells = cmark_llist_append(parser->mem, row->cells, cell);
|
143
159
|
}
|
144
|
-
row->n_columns += 1;
|
145
|
-
row->cells = cmark_llist_append(parser->mem, row->cells, cell);
|
146
160
|
}
|
147
161
|
|
148
162
|
offset += cell_matched + pipe_matched;
|
@@ -161,6 +175,26 @@ static table_row *row_from_string(cmark_syntax_extension *self,
|
|
161
175
|
return row;
|
162
176
|
}
|
163
177
|
|
178
|
+
static void try_inserting_table_header_paragraph(cmark_parser *parser,
|
179
|
+
cmark_node *parent_container,
|
180
|
+
unsigned char *parent_string,
|
181
|
+
int paragraph_offset) {
|
182
|
+
cmark_node *paragraph;
|
183
|
+
cmark_strbuf *paragraph_content;
|
184
|
+
|
185
|
+
paragraph = cmark_node_new_with_mem(CMARK_NODE_PARAGRAPH, parser->mem);
|
186
|
+
|
187
|
+
paragraph_content = unescape_pipes(parser->mem, parent_string, paragraph_offset);
|
188
|
+
cmark_strbuf_trim(paragraph_content);
|
189
|
+
cmark_node_set_string_content(paragraph, (char *) paragraph_content->ptr);
|
190
|
+
cmark_strbuf_free(paragraph_content);
|
191
|
+
parser->mem->free(paragraph_content);
|
192
|
+
|
193
|
+
if (!cmark_node_insert_before(parent_container, paragraph)) {
|
194
|
+
parser->mem->free(paragraph);
|
195
|
+
}
|
196
|
+
}
|
197
|
+
|
164
198
|
static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
|
165
199
|
cmark_parser *parser,
|
166
200
|
cmark_node *parent_container,
|
@@ -217,6 +251,11 @@ static cmark_node *try_opening_table_header(cmark_syntax_extension *self,
|
|
217
251
|
return parent_container;
|
218
252
|
}
|
219
253
|
|
254
|
+
if (header_row->paragraph_offset) {
|
255
|
+
try_inserting_table_header_paragraph(parser, parent_container, (unsigned char *)parent_string,
|
256
|
+
header_row->paragraph_offset);
|
257
|
+
}
|
258
|
+
|
220
259
|
cmark_node_set_syntax_extension(parent_container, self);
|
221
260
|
|
222
261
|
parent_container->as.opaque = parser->mem->calloc(1, sizeof(node_table));
|
data/ext/commonmarker/tasklist.c
CHANGED
@@ -9,19 +9,33 @@ typedef enum {
|
|
9
9
|
CMARK_TASKLIST_CHECKED,
|
10
10
|
} cmark_tasklist_type;
|
11
11
|
|
12
|
+
// Local constants
|
13
|
+
static const char *TYPE_STRING = "tasklist";
|
14
|
+
|
12
15
|
static const char *get_type_string(cmark_syntax_extension *extension, cmark_node *node) {
|
13
|
-
return
|
16
|
+
return TYPE_STRING;
|
14
17
|
}
|
15
18
|
|
16
|
-
|
17
|
-
|
19
|
+
|
20
|
+
// Return 1 if state was set, 0 otherwise
|
21
|
+
int cmark_gfm_extensions_set_tasklist_item_checked(cmark_node *node, bool is_checked) {
|
22
|
+
// The node has to exist, and be an extension, and actually be the right type in order to get the value.
|
23
|
+
if (!node || !node->extension || strcmp(cmark_node_get_type_string(node), TYPE_STRING))
|
18
24
|
return 0;
|
19
25
|
|
20
|
-
|
21
|
-
|
26
|
+
node->as.list.checked = is_checked;
|
27
|
+
return 1;
|
28
|
+
}
|
29
|
+
|
30
|
+
bool cmark_gfm_extensions_get_tasklist_item_checked(cmark_node *node) {
|
31
|
+
if (!node || !node->extension || strcmp(cmark_node_get_type_string(node), TYPE_STRING))
|
32
|
+
return false;
|
33
|
+
|
34
|
+
if (node->as.list.checked) {
|
35
|
+
return true;
|
22
36
|
}
|
23
37
|
else {
|
24
|
-
return
|
38
|
+
return false;
|
25
39
|
}
|
26
40
|
}
|
27
41
|
|
@@ -74,11 +88,8 @@ static cmark_node *open_tasklist_item(cmark_syntax_extension *self,
|
|
74
88
|
cmark_node_set_syntax_extension(parent_container, self);
|
75
89
|
cmark_parser_advance_offset(parser, (char *)input, 3, false);
|
76
90
|
|
77
|
-
|
78
|
-
|
79
|
-
} else {
|
80
|
-
parent_container->as.opaque = (void *)CMARK_TASKLIST_NOCHECKED;
|
81
|
-
}
|
91
|
+
// Either an upper or lower case X means the task is completed.
|
92
|
+
parent_container->as.list.checked = (strstr((char*)input, "[x]") || strstr((char*)input, "[X]"));
|
82
93
|
|
83
94
|
return NULL;
|
84
95
|
}
|
@@ -89,7 +100,7 @@ static void commonmark_render(cmark_syntax_extension *extension,
|
|
89
100
|
bool entering = (ev_type == CMARK_EVENT_ENTER);
|
90
101
|
if (entering) {
|
91
102
|
renderer->cr(renderer);
|
92
|
-
if (
|
103
|
+
if (node->as.list.checked) {
|
93
104
|
renderer->out(renderer, node, "- [x] ", false, LITERAL);
|
94
105
|
} else {
|
95
106
|
renderer->out(renderer, node, "- [ ] ", false, LITERAL);
|
@@ -110,7 +121,7 @@ static void html_render(cmark_syntax_extension *extension,
|
|
110
121
|
cmark_strbuf_puts(renderer->html, "<li");
|
111
122
|
cmark_html_render_sourcepos(node, renderer->html, options);
|
112
123
|
cmark_strbuf_putc(renderer->html, '>');
|
113
|
-
if (
|
124
|
+
if (node->as.list.checked) {
|
114
125
|
cmark_strbuf_puts(renderer->html, "<input type=\"checkbox\" checked=\"\" disabled=\"\" /> ");
|
115
126
|
} else {
|
116
127
|
cmark_strbuf_puts(renderer->html, "<input type=\"checkbox\" disabled=\"\" /> ");
|
@@ -120,6 +131,15 @@ static void html_render(cmark_syntax_extension *extension,
|
|
120
131
|
}
|
121
132
|
}
|
122
133
|
|
134
|
+
static const char *xml_attr(cmark_syntax_extension *extension,
|
135
|
+
cmark_node *node) {
|
136
|
+
if (node->as.list.checked) {
|
137
|
+
return " completed=\"true\"";
|
138
|
+
} else {
|
139
|
+
return " completed=\"false\"";
|
140
|
+
}
|
141
|
+
}
|
142
|
+
|
123
143
|
cmark_syntax_extension *create_tasklist_extension(void) {
|
124
144
|
cmark_syntax_extension *ext = cmark_syntax_extension_new("tasklist");
|
125
145
|
|
@@ -130,6 +150,7 @@ cmark_syntax_extension *create_tasklist_extension(void) {
|
|
130
150
|
cmark_syntax_extension_set_commonmark_render_func(ext, commonmark_render);
|
131
151
|
cmark_syntax_extension_set_plaintext_render_func(ext, commonmark_render);
|
132
152
|
cmark_syntax_extension_set_html_render_func(ext, html_render);
|
153
|
+
cmark_syntax_extension_set_xml_attr_func(ext, xml_attr);
|
133
154
|
|
134
155
|
return ext;
|
135
156
|
}
|
data/lib/commonmarker.rb
CHANGED
@@ -10,8 +10,7 @@ require 'commonmarker/version'
|
|
10
10
|
|
11
11
|
begin
|
12
12
|
require 'awesome_print'
|
13
|
-
rescue LoadError; end
|
14
|
-
|
13
|
+
rescue LoadError; end # rubocop:disable Lint/SuppressedException
|
15
14
|
module CommonMarker
|
16
15
|
# Public: Parses a Markdown string into an HTML string.
|
17
16
|
#
|
@@ -21,7 +20,8 @@ module CommonMarker
|
|
21
20
|
#
|
22
21
|
# Returns a {String} of converted HTML.
|
23
22
|
def self.render_html(text, options = :DEFAULT, extensions = [])
|
24
|
-
|
23
|
+
raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String)
|
24
|
+
|
25
25
|
opts = Config.process_options(options, :render)
|
26
26
|
text = text.encode('UTF-8')
|
27
27
|
html = Node.markdown_to_html(text, opts, extensions)
|
@@ -36,7 +36,8 @@ module CommonMarker
|
|
36
36
|
#
|
37
37
|
# Returns the `document` node.
|
38
38
|
def self.render_doc(text, options = :DEFAULT, extensions = [])
|
39
|
-
|
39
|
+
raise TypeError, "text must be a String; got a #{text.class}!" unless text.is_a?(String)
|
40
|
+
|
40
41
|
opts = Config.process_options(options, :parse)
|
41
42
|
text = text.encode('UTF-8')
|
42
43
|
Node.parse_document(text, text.bytesize, opts, extensions)
|
data/lib/commonmarker/config.rb
CHANGED
@@ -37,16 +37,17 @@ module CommonMarker
|
|
37
37
|
elsif option.is_a?(Array)
|
38
38
|
option = [nil] if option.empty?
|
39
39
|
# neckbearding around. the map will both check the opts and then bitwise-OR it
|
40
|
-
option.map
|
40
|
+
option.map do |o|
|
41
|
+
check_option(o, type)
|
42
|
+
type.to_h[o]
|
43
|
+
end.inject(0, :|)
|
41
44
|
else
|
42
45
|
raise TypeError, "option type must be a valid symbol or array of symbols within the #{type} context"
|
43
46
|
end
|
44
47
|
end
|
45
48
|
|
46
49
|
def self.check_option(option, type)
|
47
|
-
unless type.key?(option)
|
48
|
-
raise TypeError, "option ':#{option}' does not exist for #{type}"
|
49
|
-
end
|
50
|
+
raise TypeError, "option ':#{option}' does not exist for #{type}" unless type.key?(option)
|
50
51
|
end
|
51
52
|
end
|
52
53
|
end
|
data/lib/commonmarker/node.rb
CHANGED
@@ -8,13 +8,13 @@ module CommonMarker
|
|
8
8
|
PP_INDENT_SIZE = 2
|
9
9
|
|
10
10
|
def inspect
|
11
|
-
PP.pp(self,
|
11
|
+
PP.pp(self, +'', Float::INFINITY)
|
12
12
|
end
|
13
13
|
|
14
|
-
# @param [PrettyPrint] pp
|
15
|
-
def pretty_print(
|
16
|
-
|
17
|
-
|
14
|
+
# @param printer [PrettyPrint] pp
|
15
|
+
def pretty_print(printer)
|
16
|
+
printer.group(PP_INDENT_SIZE, "#<#{self.class}(#{type}):", '>') do
|
17
|
+
printer.breakable
|
18
18
|
|
19
19
|
attrs = %i[
|
20
20
|
sourcepos
|
@@ -34,22 +34,22 @@ module CommonMarker
|
|
34
34
|
end
|
35
35
|
end.compact
|
36
36
|
|
37
|
-
|
38
|
-
|
39
|
-
|
37
|
+
printer.seplist(attrs) do |name, value|
|
38
|
+
printer.text "#{name}="
|
39
|
+
printer.pp value
|
40
40
|
end
|
41
41
|
|
42
42
|
if first_child
|
43
|
-
|
44
|
-
|
43
|
+
printer.breakable
|
44
|
+
printer.group(PP_INDENT_SIZE) do
|
45
45
|
children = []
|
46
46
|
node = first_child
|
47
47
|
while node
|
48
48
|
children << node
|
49
49
|
node = node.next
|
50
50
|
end
|
51
|
-
|
52
|
-
|
51
|
+
printer.text 'children='
|
52
|
+
printer.pp children
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# rubocop:disable Standard/RailsViewRenderLiteral
|
3
|
-
# rubocop:disable Standard/RailsControllerRenderLiteral
|
4
2
|
|
5
3
|
require 'set'
|
6
4
|
require 'stringio'
|
@@ -10,7 +8,7 @@ module CommonMarker
|
|
10
8
|
attr_accessor :in_tight, :warnings, :in_plain
|
11
9
|
def initialize(options: :DEFAULT, extensions: [])
|
12
10
|
@opts = Config.process_options(options, :render)
|
13
|
-
@stream = StringIO.new(''
|
11
|
+
@stream = StringIO.new(+'')
|
14
12
|
@need_blocksep = false
|
15
13
|
@warnings = Set.new []
|
16
14
|
@in_tight = false
|
@@ -36,7 +34,7 @@ module CommonMarker
|
|
36
34
|
@node = node
|
37
35
|
if node.type == :document
|
38
36
|
document(node)
|
39
|
-
|
37
|
+
@stream.string
|
40
38
|
elsif @in_plain && node.type != :text && node.type != :softbreak
|
41
39
|
node.each { |child| render(child) }
|
42
40
|
else
|
@@ -57,11 +55,11 @@ module CommonMarker
|
|
57
55
|
code_block(node)
|
58
56
|
end
|
59
57
|
|
60
|
-
def reference_def(_node)
|
61
|
-
end
|
58
|
+
def reference_def(_node); end
|
62
59
|
|
63
60
|
def cr
|
64
61
|
return if @stream.string.empty? || @stream.string[-1] == "\n"
|
62
|
+
|
65
63
|
out("\n")
|
66
64
|
end
|
67
65
|
|
@@ -113,7 +111,8 @@ module CommonMarker
|
|
113
111
|
)
|
114
112
|
(?=\s|>|/>)
|
115
113
|
}xi,
|
116
|
-
'<\1'
|
114
|
+
'<\1'
|
115
|
+
)
|
117
116
|
else
|
118
117
|
str
|
119
118
|
end
|
@@ -121,6 +120,7 @@ module CommonMarker
|
|
121
120
|
|
122
121
|
def sourcepos(node)
|
123
122
|
return '' unless option_enabled?(:SOURCEPOS)
|
123
|
+
|
124
124
|
s = node.sourcepos
|
125
125
|
" data-sourcepos=\"#{s[:start_line]}:#{s[:start_column]}-" \
|
126
126
|
"#{s[:end_line]}:#{s[:end_column]}\""
|
@@ -2,15 +2,9 @@
|
|
2
2
|
|
3
3
|
module CommonMarker
|
4
4
|
class HtmlRenderer < Renderer
|
5
|
-
def render(node)
|
6
|
-
super(node)
|
7
|
-
end
|
8
|
-
|
9
5
|
def document(_)
|
10
6
|
super
|
11
|
-
if @written_footnote_ix
|
12
|
-
out("</ol>\n</section>\n")
|
13
|
-
end
|
7
|
+
out("</ol>\n</section>\n") if @written_footnote_ix
|
14
8
|
end
|
15
9
|
|
16
10
|
def header(node)
|
@@ -71,12 +65,13 @@ module CommonMarker
|
|
71
65
|
|
72
66
|
def tasklist(node)
|
73
67
|
return '' unless tasklist?(node)
|
68
|
+
|
74
69
|
state = if checked?(node)
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
70
|
+
'checked="" disabled=""'
|
71
|
+
else
|
72
|
+
'disabled=""'
|
73
|
+
end
|
74
|
+
"><input type=\"checkbox\" #{state} /"
|
80
75
|
end
|
81
76
|
|
82
77
|
def blockquote(node)
|
@@ -97,9 +92,7 @@ module CommonMarker
|
|
97
92
|
block do
|
98
93
|
if option_enabled?(:GITHUB_PRE_LANG)
|
99
94
|
out("<pre#{sourcepos(node)}")
|
100
|
-
if node.fence_info && !node.fence_info.empty?
|
101
|
-
out(' lang="', node.fence_info.split(/\s+/)[0], '"')
|
102
|
-
end
|
95
|
+
out(' lang="', node.fence_info.split(/\s+/)[0], '"') if node.fence_info && !node.fence_info.empty?
|
103
96
|
out('><code>')
|
104
97
|
else
|
105
98
|
out("<pre#{sourcepos(node)}><code")
|
@@ -142,9 +135,7 @@ module CommonMarker
|
|
142
135
|
|
143
136
|
def link(node)
|
144
137
|
out('<a href="', node.url.nil? ? '' : escape_href(node.url), '"')
|
145
|
-
if node.title && !node.title.empty?
|
146
|
-
out(' title="', escape_html(node.title), '"')
|
147
|
-
end
|
138
|
+
out(' title="', escape_html(node.title), '"') if node.title && !node.title.empty?
|
148
139
|
out('>', :children, '</a>')
|
149
140
|
end
|
150
141
|
|
@@ -153,9 +144,7 @@ module CommonMarker
|
|
153
144
|
plain do
|
154
145
|
out(' alt="', :children, '"')
|
155
146
|
end
|
156
|
-
if node.title && !node.title.empty?
|
157
|
-
out(' title="', escape_html(node.title), '"')
|
158
|
-
end
|
147
|
+
out(' title="', escape_html(node.title), '"') if node.title && !node.title.empty?
|
159
148
|
out(' />')
|
160
149
|
end
|
161
150
|
|
@@ -169,7 +158,7 @@ module CommonMarker
|
|
169
158
|
out('</code>')
|
170
159
|
end
|
171
160
|
|
172
|
-
def linebreak(
|
161
|
+
def linebreak(_node)
|
173
162
|
out("<br />\n")
|
174
163
|
end
|
175
164
|
|
@@ -210,9 +199,9 @@ module CommonMarker
|
|
210
199
|
|
211
200
|
def table_cell(node)
|
212
201
|
align = case @alignments[@column_index]
|
213
|
-
when :left
|
214
|
-
when :right
|
215
|
-
when :center
|
202
|
+
when :left then ' align="left"'
|
203
|
+
when :right then ' align="right"'
|
204
|
+
when :center then ' align="center"'
|
216
205
|
else; ''
|
217
206
|
end
|
218
207
|
out(@in_header ? "<th#{align}#{sourcepos(node)}>" : "<td#{align}#{sourcepos(node)}>", :children, @in_header ? "</th>\n" : "</td>\n")
|
@@ -228,28 +217,27 @@ module CommonMarker
|
|
228
217
|
end
|
229
218
|
|
230
219
|
def footnote_definition(_)
|
231
|
-
|
220
|
+
unless @footnote_ix
|
232
221
|
out("<section class=\"footnotes\">\n<ol>\n")
|
233
222
|
@footnote_ix = 0
|
234
223
|
end
|
235
224
|
|
236
225
|
@footnote_ix += 1
|
237
|
-
out("<li id=\"fn
|
238
|
-
if out_footnote_backref
|
239
|
-
out("\n")
|
240
|
-
end
|
226
|
+
out("<li id=\"fn#{@footnote_ix}\">\n", :children)
|
227
|
+
out("\n") if out_footnote_backref
|
241
228
|
out("</li>\n")
|
242
|
-
|
243
|
-
|
229
|
+
# </ol>
|
230
|
+
# </section>
|
244
231
|
end
|
245
232
|
|
246
233
|
private
|
247
234
|
|
248
235
|
def out_footnote_backref
|
249
236
|
return false if @written_footnote_ix == @footnote_ix
|
237
|
+
|
250
238
|
@written_footnote_ix = @footnote_ix
|
251
239
|
|
252
|
-
out("<a href=\"#fnref
|
240
|
+
out("<a href=\"#fnref#{@footnote_ix}\" class=\"footnote-backref\">↩</a>")
|
253
241
|
true
|
254
242
|
end
|
255
243
|
|
@@ -258,8 +246,7 @@ module CommonMarker
|
|
258
246
|
end
|
259
247
|
|
260
248
|
def checked?(node)
|
261
|
-
node.
|
249
|
+
node.tasklist_item_checked?
|
262
250
|
end
|
263
|
-
|
264
251
|
end
|
265
252
|
end
|