commonmarker 0.23.1 → 0.23.5
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/Rakefile +56 -55
- data/bin/commonmarker +2 -7
- data/commonmarker.gemspec +27 -26
- data/ext/commonmarker/blocks.c +13 -2
- data/ext/commonmarker/cmark-gfm_version.h +2 -2
- data/ext/commonmarker/commonmark.c +14 -4
- data/ext/commonmarker/commonmarker.c +30 -44
- data/ext/commonmarker/ext_scanners.c +360 -640
- data/ext/commonmarker/footnotes.c +23 -0
- data/ext/commonmarker/footnotes.h +2 -0
- data/ext/commonmarker/html.c +40 -19
- data/ext/commonmarker/inlines.c +69 -11
- data/ext/commonmarker/node.h +7 -0
- data/ext/commonmarker/scanners.c +2438 -2450
- data/ext/commonmarker/table.c +98 -53
- data/lib/commonmarker/config.rb +1 -1
- data/lib/commonmarker/node/inspect.rb +8 -18
- data/lib/commonmarker/node.rb +6 -6
- data/lib/commonmarker/renderer/html_renderer.rb +37 -37
- data/lib/commonmarker/renderer.rb +5 -5
- data/lib/commonmarker/version.rb +1 -1
- data/lib/commonmarker.rb +9 -11
- metadata +6 -57
- data/test/benchmark.rb +0 -32
- data/test/fixtures/curly.md +0 -1
- data/test/fixtures/dingus.md +0 -10
- data/test/fixtures/strong.md +0 -1
- data/test/fixtures/table.md +0 -10
- data/test/test_attributes.rb +0 -24
- data/test/test_basics.rb +0 -35
- data/test/test_commands.rb +0 -72
- data/test/test_commonmark.rb +0 -36
- data/test/test_doc.rb +0 -130
- data/test/test_encoding.rb +0 -23
- data/test/test_extensions.rb +0 -116
- data/test/test_footnotes.rb +0 -48
- data/test/test_gc.rb +0 -47
- data/test/test_helper.rb +0 -71
- data/test/test_linebreaks.rb +0 -15
- data/test/test_maliciousness.rb +0 -262
- data/test/test_node.rb +0 -89
- data/test/test_options.rb +0 -37
- data/test/test_pathological_inputs.rb +0 -94
- data/test/test_plaintext.rb +0 -46
- data/test/test_renderer.rb +0 -47
- data/test/test_smartpunct.rb +0 -27
- data/test/test_spec.rb +0 -30
- data/test/test_tasklists.rb +0 -43
- data/test/test_xml.rb +0 -107
data/test/test_gc.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# rubocop:disable Lint/UselessAssignment
|
4
|
-
require 'test_helper'
|
5
|
-
|
6
|
-
class TestNode < Minitest::Test
|
7
|
-
# These tests are somewhat fragile. It would be better to allocate lots
|
8
|
-
# of memory after a GC run to make sure that potentially freed memory
|
9
|
-
# isn't valid by accident.
|
10
|
-
|
11
|
-
def test_drop_parent_reference
|
12
|
-
doc = CommonMarker.render_doc('Hi *there*')
|
13
|
-
text = doc.first_child.last_child.first_child
|
14
|
-
doc = nil
|
15
|
-
GC.start
|
16
|
-
# Test that doc has not been freed.
|
17
|
-
assert_equal 'there', text.string_content
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_drop_child_reference
|
21
|
-
doc = CommonMarker.render_doc('Hi *there*')
|
22
|
-
text = doc.first_child.last_child.first_child
|
23
|
-
text = nil
|
24
|
-
GC.start
|
25
|
-
# Test that the cached child object is still valid.
|
26
|
-
text = doc.first_child.last_child.first_child
|
27
|
-
assert_equal 'there', text.string_content
|
28
|
-
end
|
29
|
-
|
30
|
-
def test_remove_parent
|
31
|
-
doc = CommonMarker.render_doc('Hi *there*')
|
32
|
-
para = doc.first_child
|
33
|
-
para.delete
|
34
|
-
doc = nil
|
35
|
-
para = nil
|
36
|
-
# TODO: Test that the `para` node was actually freed after unlinking.
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_add_parent
|
40
|
-
doc = Node.new(:document)
|
41
|
-
hrule = Node.new(:hrule)
|
42
|
-
doc.append_child(hrule)
|
43
|
-
# If the hrule node was erroneously freed, this would result in a double
|
44
|
-
# free.
|
45
|
-
end
|
46
|
-
end
|
47
|
-
# rubocop:enable Lint/UselessAssignment
|
data/test/test_helper.rb
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'commonmarker'
|
4
|
-
require 'minitest/autorun'
|
5
|
-
require 'minitest/pride'
|
6
|
-
require 'minitest/focus'
|
7
|
-
|
8
|
-
include CommonMarker # rubocop:disable Style/MixinUsage
|
9
|
-
|
10
|
-
FIXTURES_DIR = File.join(File.dirname(__FILE__), 'fixtures')
|
11
|
-
|
12
|
-
def fixtures_file(file)
|
13
|
-
File.read(File.join(FIXTURES_DIR, file), encoding: 'utf-8')
|
14
|
-
end
|
15
|
-
|
16
|
-
def make_bin(file, args = '')
|
17
|
-
`ruby bin/commonmarker #{File.join(FIXTURES_DIR, file)} #{args}`.chomp
|
18
|
-
end
|
19
|
-
|
20
|
-
def open_spec_file(filename)
|
21
|
-
line_number = 0
|
22
|
-
start_line = 0
|
23
|
-
end_line = 0
|
24
|
-
example_number = 0
|
25
|
-
markdown_lines = []
|
26
|
-
html_lines = []
|
27
|
-
state = 0 # 0 regular text, 1 markdown example, 2 html output
|
28
|
-
headertext = ''
|
29
|
-
tests = []
|
30
|
-
extensions = []
|
31
|
-
|
32
|
-
header_re = Regexp.new('#+ ')
|
33
|
-
filepath = File.join('ext', 'commonmarker', 'cmark-upstream', 'test', filename)
|
34
|
-
|
35
|
-
File.readlines(filepath, encoding: 'utf-8').each do |line|
|
36
|
-
line_number += 1
|
37
|
-
|
38
|
-
l = line.strip
|
39
|
-
if l =~ /^`{32} example(.*)$/
|
40
|
-
state = 1
|
41
|
-
extensions = Regexp.last_match(1).split
|
42
|
-
elsif l == '`' * 32
|
43
|
-
state = 0
|
44
|
-
example_number += 1
|
45
|
-
end_line = line_number
|
46
|
-
tests << {
|
47
|
-
markdown: markdown_lines.join.tr('→', "\t"),
|
48
|
-
html: html_lines.join.tr('→', "\t").rstrip,
|
49
|
-
example: example_number,
|
50
|
-
start_line: start_line,
|
51
|
-
end_line: end_line,
|
52
|
-
section: headertext,
|
53
|
-
extensions: extensions.map(&:to_sym)
|
54
|
-
}
|
55
|
-
start_line = 0
|
56
|
-
markdown_lines = []
|
57
|
-
html_lines = []
|
58
|
-
elsif l == '.'
|
59
|
-
state = 2
|
60
|
-
elsif state == 1
|
61
|
-
start_line = line_number - 1 if start_line.zero?
|
62
|
-
markdown_lines << line.to_s
|
63
|
-
elsif state == 2
|
64
|
-
html_lines << line.to_s
|
65
|
-
elsif state.zero? && header_re.match(line)
|
66
|
-
headertext = line.sub(header_re, '').strip
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
tests
|
71
|
-
end
|
data/test/test_linebreaks.rb
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class TestLinebreaks < Minitest::Test
|
6
|
-
def test_hardbreak_no_spaces
|
7
|
-
doc = CommonMarker.render_doc("foo\nbaz")
|
8
|
-
assert_equal "<p>foo<br />\nbaz</p>\n", doc.to_html(:HARDBREAKS)
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_hardbreak_with_spaces
|
12
|
-
doc = CommonMarker.render_doc("foo \nbaz")
|
13
|
-
assert_equal "<p>foo<br />\nbaz</p>\n", doc.to_html(:HARDBREAKS)
|
14
|
-
end
|
15
|
-
end
|
data/test/test_maliciousness.rb
DELETED
@@ -1,262 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
module CommonMarker
|
6
|
-
class TestMaliciousness < Minitest::Test
|
7
|
-
def setup
|
8
|
-
@doc = CommonMarker.render_doc('Hi *there*')
|
9
|
-
end
|
10
|
-
|
11
|
-
def test_init_with_bad_type
|
12
|
-
assert_raises TypeError do
|
13
|
-
Node.new(123)
|
14
|
-
end
|
15
|
-
|
16
|
-
assert_raises NodeError do
|
17
|
-
Node.new(:totes_fake)
|
18
|
-
end
|
19
|
-
|
20
|
-
assert_raises TypeError do
|
21
|
-
Node.new([])
|
22
|
-
end
|
23
|
-
|
24
|
-
assert_raises TypeError do
|
25
|
-
Node.new([23])
|
26
|
-
end
|
27
|
-
|
28
|
-
assert_raises TypeError do
|
29
|
-
Node.new(nil)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def test_rendering_with_bad_type
|
34
|
-
assert_raises TypeError do
|
35
|
-
CommonMarker.render_html("foo \n baz", 123)
|
36
|
-
end
|
37
|
-
|
38
|
-
assert_raises TypeError do
|
39
|
-
CommonMarker.render_html("foo \n baz", :totes_fake)
|
40
|
-
end
|
41
|
-
|
42
|
-
assert_raises TypeError do
|
43
|
-
CommonMarker.render_html("foo \n baz", [])
|
44
|
-
end
|
45
|
-
|
46
|
-
assert_raises TypeError do
|
47
|
-
CommonMarker.render_html("foo \n baz", [23])
|
48
|
-
end
|
49
|
-
|
50
|
-
assert_raises TypeError do
|
51
|
-
CommonMarker.render_html("foo \n baz", nil)
|
52
|
-
end
|
53
|
-
|
54
|
-
assert_raises TypeError do
|
55
|
-
CommonMarker.render_html("foo \n baz", [:SMART, 'totes_fake'])
|
56
|
-
end
|
57
|
-
|
58
|
-
assert_raises TypeError do
|
59
|
-
CommonMarker.render_html(123)
|
60
|
-
end
|
61
|
-
|
62
|
-
assert_raises TypeError do
|
63
|
-
CommonMarker.render_html([123])
|
64
|
-
end
|
65
|
-
|
66
|
-
assert_raises TypeError do
|
67
|
-
CommonMarker.render_html(nil)
|
68
|
-
end
|
69
|
-
|
70
|
-
assert_raises TypeError do
|
71
|
-
CommonMarker.render_doc("foo \n baz", 123)
|
72
|
-
end
|
73
|
-
|
74
|
-
err = assert_raises TypeError do
|
75
|
-
CommonMarker.render_doc("foo \n baz", :safe)
|
76
|
-
end
|
77
|
-
assert_equal('option \':safe\' does not exist for CommonMarker::Config::OPTS[:parse]', err.message)
|
78
|
-
|
79
|
-
assert_raises TypeError do
|
80
|
-
CommonMarker.render_doc("foo \n baz", :totes_fake)
|
81
|
-
end
|
82
|
-
|
83
|
-
assert_raises TypeError do
|
84
|
-
CommonMarker.render_doc("foo \n baz", [])
|
85
|
-
end
|
86
|
-
|
87
|
-
assert_raises TypeError do
|
88
|
-
CommonMarker.render_doc("foo \n baz", [23])
|
89
|
-
end
|
90
|
-
|
91
|
-
assert_raises TypeError do
|
92
|
-
CommonMarker.render_doc("foo \n baz", nil)
|
93
|
-
end
|
94
|
-
|
95
|
-
assert_raises TypeError do
|
96
|
-
CommonMarker.render_doc("foo \n baz", [:SMART, 'totes_fake'])
|
97
|
-
end
|
98
|
-
|
99
|
-
assert_raises TypeError do
|
100
|
-
CommonMarker.render_doc(123)
|
101
|
-
end
|
102
|
-
|
103
|
-
assert_raises TypeError do
|
104
|
-
CommonMarker.render_doc([123])
|
105
|
-
end
|
106
|
-
|
107
|
-
assert_raises TypeError do
|
108
|
-
CommonMarker.render_doc(nil)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
def test_bad_set_string_content
|
113
|
-
assert_raises TypeError do
|
114
|
-
@doc.string_content = 123
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def test_bad_walking
|
119
|
-
assert_nil @doc.parent
|
120
|
-
assert_nil @doc.previous
|
121
|
-
end
|
122
|
-
|
123
|
-
def test_bad_insertion
|
124
|
-
code = Node.new(:code)
|
125
|
-
assert_raises NodeError do
|
126
|
-
@doc.insert_before(code)
|
127
|
-
end
|
128
|
-
|
129
|
-
paragraph = Node.new(:paragraph)
|
130
|
-
assert_raises NodeError do
|
131
|
-
@doc.insert_after(paragraph)
|
132
|
-
end
|
133
|
-
|
134
|
-
document = Node.new(:document)
|
135
|
-
assert_raises NodeError do
|
136
|
-
@doc.prepend_child(document)
|
137
|
-
end
|
138
|
-
|
139
|
-
assert_raises NodeError do
|
140
|
-
@doc.append_child(document)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def test_bad_url_get
|
145
|
-
assert_raises NodeError do
|
146
|
-
@doc.url
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def test_bad_url_set
|
151
|
-
assert_raises NodeError do
|
152
|
-
@doc.url = '123'
|
153
|
-
end
|
154
|
-
|
155
|
-
link = CommonMarker.render_doc('[GitHub](https://www.github.com)').first_child.first_child
|
156
|
-
assert_raises TypeError do
|
157
|
-
link.url = 123
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def test_bad_title_get
|
162
|
-
assert_raises NodeError do
|
163
|
-
@doc.title
|
164
|
-
end
|
165
|
-
end
|
166
|
-
|
167
|
-
def test_bad_title_set
|
168
|
-
assert_raises NodeError do
|
169
|
-
@doc.title = '123'
|
170
|
-
end
|
171
|
-
|
172
|
-
image = CommonMarker.render_doc('![alt text](https://github.com/favicon.ico "Favicon")')
|
173
|
-
image = image.first_child.first_child
|
174
|
-
assert_raises TypeError do
|
175
|
-
image.title = 123
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
def test_bad_header_level_get
|
180
|
-
assert_raises NodeError do
|
181
|
-
@doc.header_level
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def test_bad_header_level_set
|
186
|
-
assert_raises NodeError do
|
187
|
-
@doc.header_level = 1
|
188
|
-
end
|
189
|
-
|
190
|
-
header = CommonMarker.render_doc('### Header Three').first_child
|
191
|
-
assert_raises TypeError do
|
192
|
-
header.header_level = '123'
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
def test_bad_list_type_get
|
197
|
-
assert_raises NodeError do
|
198
|
-
@doc.list_type
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
def test_bad_list_type_set
|
203
|
-
assert_raises NodeError do
|
204
|
-
@doc.list_type = :bullet_list
|
205
|
-
end
|
206
|
-
|
207
|
-
ul_list = CommonMarker.render_doc("* Bullet\n*Bullet").first_child
|
208
|
-
assert_raises NodeError do
|
209
|
-
ul_list.list_type = :fake
|
210
|
-
end
|
211
|
-
assert_raises TypeError do
|
212
|
-
ul_list.list_type = 1234
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def test_bad_list_start_get
|
217
|
-
assert_raises NodeError do
|
218
|
-
@doc.list_start
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def test_bad_list_start_set
|
223
|
-
assert_raises NodeError do
|
224
|
-
@doc.list_start = 12
|
225
|
-
end
|
226
|
-
|
227
|
-
ol_list = CommonMarker.render_doc("1. One\n2. Two").first_child
|
228
|
-
assert_raises TypeError do
|
229
|
-
ol_list.list_start = :fake
|
230
|
-
end
|
231
|
-
end
|
232
|
-
|
233
|
-
def test_bad_list_tight_get
|
234
|
-
assert_raises NodeError do
|
235
|
-
@doc.list_tight
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
def test_bad_list_tight_set
|
240
|
-
assert_raises NodeError do
|
241
|
-
@doc.list_tight = false
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
def test_bad_fence_info_get
|
246
|
-
assert_raises NodeError do
|
247
|
-
@doc.fence_info
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
def test_bad_fence_info_set
|
252
|
-
assert_raises NodeError do
|
253
|
-
@doc.fence_info = 'ruby'
|
254
|
-
end
|
255
|
-
|
256
|
-
fence = CommonMarker.render_doc("``` ruby\nputs 'wow'\n```").first_child
|
257
|
-
assert_raises TypeError do
|
258
|
-
fence.fence_info = 123
|
259
|
-
end
|
260
|
-
end
|
261
|
-
end
|
262
|
-
end
|
data/test/test_node.rb
DELETED
@@ -1,89 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class TestNode < Minitest::Test
|
6
|
-
def setup
|
7
|
-
@doc = CommonMarker.render_doc('Hi *there*, I am mostly text!')
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_walk
|
11
|
-
nodes = []
|
12
|
-
@doc.walk do |node|
|
13
|
-
nodes << node.type
|
14
|
-
end
|
15
|
-
assert_equal %i[document paragraph text emph text text], nodes
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_each
|
19
|
-
nodes = []
|
20
|
-
@doc.first_child.each do |node|
|
21
|
-
nodes << node.type
|
22
|
-
end
|
23
|
-
assert_equal %i[text emph text], nodes
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_deprecated_each_child
|
27
|
-
nodes = []
|
28
|
-
_, err = capture_io do
|
29
|
-
@doc.first_child.each_child do |node|
|
30
|
-
nodes << node.type
|
31
|
-
end
|
32
|
-
end
|
33
|
-
assert_equal %i[text emph text], nodes
|
34
|
-
assert_match(/`each_child` is deprecated/, err)
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_select
|
38
|
-
nodes = @doc.first_child.select { |node| node.type == :text }
|
39
|
-
assert_equal CommonMarker::Node, nodes.first.class
|
40
|
-
assert_equal %i[text text], nodes.map(&:type)
|
41
|
-
end
|
42
|
-
|
43
|
-
def test_map
|
44
|
-
nodes = @doc.first_child.map(&:type)
|
45
|
-
assert_equal %i[text emph text], nodes
|
46
|
-
end
|
47
|
-
|
48
|
-
def test_insert_illegal
|
49
|
-
assert_raises NodeError do
|
50
|
-
@doc.insert_before(@doc)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
def test_to_html
|
55
|
-
assert_equal "<p>Hi <em>there</em>, I am mostly text!</p>\n", @doc.to_html
|
56
|
-
end
|
57
|
-
|
58
|
-
def test_html_renderer
|
59
|
-
renderer = HtmlRenderer.new
|
60
|
-
result = renderer.render(@doc)
|
61
|
-
assert_equal "<p>Hi <em>there</em>, I am mostly text!</p>\n", result
|
62
|
-
end
|
63
|
-
|
64
|
-
def test_walk_and_set_string_content
|
65
|
-
@doc.walk do |node|
|
66
|
-
node.string_content = 'world' if node.type == :text && node.string_content == 'there'
|
67
|
-
end
|
68
|
-
result = HtmlRenderer.new.render(@doc)
|
69
|
-
assert_equal "<p>Hi <em>world</em>, I am mostly text!</p>\n", result
|
70
|
-
end
|
71
|
-
|
72
|
-
def test_walk_and_delete_node
|
73
|
-
@doc.walk do |node|
|
74
|
-
if node.type == :emph
|
75
|
-
node.insert_before(node.first_child)
|
76
|
-
node.delete
|
77
|
-
end
|
78
|
-
end
|
79
|
-
assert_equal "<p>Hi there, I am mostly text!</p>\n", @doc.to_html
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_inspect
|
83
|
-
assert_match(/#<CommonMarker::Node\(document\):/, @doc.inspect)
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_pretty_print
|
87
|
-
assert_match(/#<CommonMarker::Node\(document\):/, PP.pp(@doc, +''))
|
88
|
-
end
|
89
|
-
end
|
data/test/test_options.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class TestExtensions < Minitest::Test
|
6
|
-
def test_full_info_string
|
7
|
-
md = <<~MD
|
8
|
-
```ruby
|
9
|
-
module Foo
|
10
|
-
```
|
11
|
-
MD
|
12
|
-
|
13
|
-
CommonMarker.render_html(md, :FULL_INFO_STRING).tap do |out|
|
14
|
-
assert_includes out, '<pre><code class="language-ruby">'
|
15
|
-
end
|
16
|
-
|
17
|
-
md = <<~MD
|
18
|
-
```ruby my info string
|
19
|
-
module Foo
|
20
|
-
```
|
21
|
-
MD
|
22
|
-
|
23
|
-
CommonMarker.render_html(md, :FULL_INFO_STRING).tap do |out|
|
24
|
-
assert_includes out, '<pre><code class="language-ruby" data-meta="my info string">'
|
25
|
-
end
|
26
|
-
|
27
|
-
md = <<~MD
|
28
|
-
```ruby my \x00 string
|
29
|
-
module Foo
|
30
|
-
```
|
31
|
-
MD
|
32
|
-
|
33
|
-
CommonMarker.render_html(md, :FULL_INFO_STRING).tap do |out|
|
34
|
-
assert_includes out, %(<pre><code class="language-ruby" data-meta="my � string">)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,94 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
require 'minitest/benchmark' if ENV['BENCH']
|
5
|
-
|
6
|
-
def markdown(str)
|
7
|
-
CommonMarker.render_doc(str).to_html
|
8
|
-
end
|
9
|
-
|
10
|
-
# list of pairs consisting of input and a regex that must match the output.
|
11
|
-
pathological = {
|
12
|
-
'nested strong emph' =>
|
13
|
-
["#{'*a **a ' * 65_000}b#{' a** a*' * 65_000}",
|
14
|
-
Regexp.compile('(<em>a <strong>a ){65_000}b( a</strong> a</em>){65_000}')],
|
15
|
-
'many emph closers with no openers' =>
|
16
|
-
[('a_ ' * 65_000),
|
17
|
-
Regexp.compile('(a[_] ){64999}a_')],
|
18
|
-
'many emph openers with no closers' =>
|
19
|
-
[('_a ' * 65_000),
|
20
|
-
Regexp.compile('(_a ){64999}_a')],
|
21
|
-
'many link closers with no openers' =>
|
22
|
-
[('a]' * 65_000),
|
23
|
-
Regexp.compile('(a\]){65_000}')],
|
24
|
-
'many link openers with no closers' =>
|
25
|
-
[('[a' * 65_000),
|
26
|
-
Regexp.compile('(\[a){65_000}')],
|
27
|
-
'mismatched openers and closers' =>
|
28
|
-
[('*a_ ' * 50_000),
|
29
|
-
Regexp.compile('([*]a[_] ){49999}[*]a_')],
|
30
|
-
'link openers and emph closers' =>
|
31
|
-
[('[ a_' * 50_000),
|
32
|
-
Regexp.compile('(\[ a_){50000}')],
|
33
|
-
'hard link/emph case' =>
|
34
|
-
['**x [a*b**c*](d)',
|
35
|
-
Regexp.compile('\\*\\*x <a href=\'d\'>a<em>b</em><em>c</em></a>')],
|
36
|
-
'nested brackets' =>
|
37
|
-
["#{'[' * 50_000}a#{']' * 50_000}",
|
38
|
-
Regexp.compile('\[{50000}a\]{50000}')],
|
39
|
-
'nested block quotes' =>
|
40
|
-
["#{'> ' * 50_000}a",
|
41
|
-
Regexp.compile('(<blockquote>\n){50000}')],
|
42
|
-
'U+0000 in input' =>
|
43
|
-
['abc\u0000de\u0000',
|
44
|
-
Regexp.compile('abc\ufffd?de\ufffd?')]
|
45
|
-
}
|
46
|
-
|
47
|
-
pathological.each_pair do |name, description|
|
48
|
-
define_method("test_#{name}") do
|
49
|
-
input, = description
|
50
|
-
assert markdown(input)
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
if ENV['BENCH']
|
55
|
-
class PathologicalInputsPerformanceTest < Minitest::Benchmark
|
56
|
-
def test_bench_pathological_one
|
57
|
-
assert_performance_linear 0.99 do |n|
|
58
|
-
star = '*' * (n * 10)
|
59
|
-
markdown("#{star}#{star}hi#{star}#{star}")
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_bench_pathological_two
|
64
|
-
assert_performance_linear 0.99 do |n|
|
65
|
-
c = '`t`t`t`t`t`t' * (n * 10)
|
66
|
-
markdown(c)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_bench_pathological_three
|
71
|
-
assert_performance_linear 0.99 do |n|
|
72
|
-
markdown(" [a]: #{'A' * n}\n\n#{'[a][]' * n}\n")
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def test_bench_pathological_four
|
77
|
-
assert_performance_linear 0.5 do |n|
|
78
|
-
markdown("#{'[' * n}a#{']' * n}")
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_bench_pathological_five
|
83
|
-
assert_performance_linear 0.99 do |n|
|
84
|
-
markdown("#{'**a *a ' * n}#{'a* a**' * n}")
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def test_bench_unbound_recursion
|
89
|
-
assert_performance_linear 0.99 do |n|
|
90
|
-
markdown("#{'[' * n}foo#{'](bar)' * n}")
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
data/test/test_plaintext.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class TestPlaintext < Minitest::Test
|
6
|
-
def setup
|
7
|
-
@markdown = <<~MD
|
8
|
-
Hi *there*!
|
9
|
-
|
10
|
-
1. I am a numeric list.
|
11
|
-
2. I continue the list.
|
12
|
-
* Suddenly, an unordered list!
|
13
|
-
* What fun!
|
14
|
-
|
15
|
-
Okay, _enough_.
|
16
|
-
|
17
|
-
| a | b |
|
18
|
-
| --- | --- |
|
19
|
-
| c | d |
|
20
|
-
MD
|
21
|
-
end
|
22
|
-
|
23
|
-
def render_doc(doc)
|
24
|
-
CommonMarker.render_doc(doc, :DEFAULT, %i[table])
|
25
|
-
end
|
26
|
-
|
27
|
-
def test_to_commonmark
|
28
|
-
compare = render_doc(@markdown).to_plaintext
|
29
|
-
|
30
|
-
assert_equal <<~PLAINTEXT, compare
|
31
|
-
Hi there!
|
32
|
-
|
33
|
-
1. I am a numeric list.
|
34
|
-
2. I continue the list.
|
35
|
-
|
36
|
-
- Suddenly, an unordered list!
|
37
|
-
- What fun!
|
38
|
-
|
39
|
-
Okay, enough.
|
40
|
-
|
41
|
-
| a | b |
|
42
|
-
| --- | --- |
|
43
|
-
| c | d |
|
44
|
-
PLAINTEXT
|
45
|
-
end
|
46
|
-
end
|
data/test/test_renderer.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'test_helper'
|
4
|
-
|
5
|
-
class TestRenderer < Minitest::Test
|
6
|
-
def setup
|
7
|
-
@doc = CommonMarker.render_doc('Hi *there*')
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_html_renderer
|
11
|
-
renderer = HtmlRenderer.new
|
12
|
-
result = renderer.render(@doc)
|
13
|
-
assert_equal "<p>Hi <em>there</em></p>\n", result
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_multiple_tables
|
17
|
-
content = <<~DOC
|
18
|
-
| Input | Expected | Actual |
|
19
|
-
| ----------- | ---------------- | --------- |
|
20
|
-
| One | Two | Three |
|
21
|
-
|
22
|
-
| Header | Row | Example |
|
23
|
-
| :------: | ---: | :------ |
|
24
|
-
| Foo | Bar | Baz |
|
25
|
-
DOC
|
26
|
-
doc = CommonMarker.render_doc(content, :DEFAULT, %i[autolink table tagfilter])
|
27
|
-
results = CommonMarker::HtmlRenderer.new.render(doc)
|
28
|
-
assert_equal 2, results.scan(/<tbody>/).size
|
29
|
-
end
|
30
|
-
|
31
|
-
def test_escape_html_encoding
|
32
|
-
my_renderer = Class.new(HtmlRenderer) do
|
33
|
-
attr_reader :input_encoding, :output_encoding
|
34
|
-
|
35
|
-
def text(node)
|
36
|
-
@input_encoding = node.string_content.encoding
|
37
|
-
escape_html(node.string_content).tap do |escaped|
|
38
|
-
@output_encoding = escaped.encoding
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
renderer = my_renderer.new
|
44
|
-
assert_equal Encoding::UTF_8, renderer.render(@doc).encoding
|
45
|
-
assert_equal renderer.input_encoding, renderer.output_encoding
|
46
|
-
end
|
47
|
-
end
|