greenmat 3.2.0.2 → 3.2.2.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/CHANGELOG.md +4 -0
- data/README.md +33 -0
- data/bin/greenmat +40 -4
- data/ext/greenmat/buffer.c +6 -6
- data/ext/greenmat/buffer.h +1 -1
- data/ext/greenmat/gm_markdown.c +7 -3
- data/ext/greenmat/gm_render.c +8 -13
- data/ext/greenmat/html.c +25 -81
- data/ext/greenmat/html.h +1 -7
- data/ext/greenmat/markdown.c +8 -17
- data/ext/greenmat/markdown.h +3 -0
- data/greenmat.gemspec +2 -1
- data/lib/greenmat.rb +1 -1
- data/lib/greenmat/compat.rb +3 -0
- data/lib/greenmat/version.rb +1 -1
- data/tasks/greenmat.rake +32 -1
- data/test/custom_render_test.rb +1 -1
- data/test/greenmat_compat_test.rb +6 -6
- data/test/html_render_test.rb +76 -77
- data/test/html_toc_render_test.rb +9 -36
- data/test/markdown_test.rb +26 -52
- data/test/test_helper.rb +11 -15
- metadata +18 -7
- data/lib/greenmat/cli.rb +0 -86
- data/test/greenmat_bin_test.rb +0 -80
data/ext/greenmat/markdown.h
CHANGED
data/greenmat.gemspec
CHANGED
@@ -21,8 +21,9 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.executables = ["greenmat"]
|
22
22
|
s.require_paths = ["lib"]
|
23
23
|
|
24
|
+
s.add_development_dependency "nokogiri", "~> 1.6.0"
|
24
25
|
s.add_development_dependency "rake-compiler", "~> 0.8.3"
|
25
26
|
s.add_development_dependency "rspec", "~> 3.2"
|
26
27
|
s.add_development_dependency "rubygems-xcodeproj_generator", '~> 0.1'
|
27
|
-
s.add_development_dependency "test-unit", "~>
|
28
|
+
s.add_development_dependency "test-unit", "~> 2.5.4"
|
28
29
|
end
|
data/lib/greenmat.rb
CHANGED
data/lib/greenmat/compat.rb
CHANGED
data/lib/greenmat/version.rb
CHANGED
data/tasks/greenmat.rake
CHANGED
@@ -3,6 +3,35 @@ namespace :greenmat do
|
|
3
3
|
task :rename_project do
|
4
4
|
ProjectRenamer.rename
|
5
5
|
end
|
6
|
+
|
7
|
+
desc 'Set up git remote for redcarpet as `upstream`.'
|
8
|
+
task :setup_upstream do
|
9
|
+
sh 'git remote add upstream https://github.com/vmg/redcarpet.git'
|
10
|
+
sh 'git remote update'
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'Merge upstream branch while renaming project (BRANCH=branch_name).'
|
14
|
+
task :merge_upstream do
|
15
|
+
abort 'The current repository is not clean.' unless `git status --porcelain`.empty?
|
16
|
+
|
17
|
+
main_branch = `git rev-parse --abbrev-ref HEAD`.chomp
|
18
|
+
target_branch = ENV['BRANCH'] || 'upstream/master'
|
19
|
+
target_merge_branch = "merge-#{target_branch}"
|
20
|
+
|
21
|
+
puts "Merging #{target_branch.inspect} into #{main_branch.inspect}"
|
22
|
+
|
23
|
+
require 'fileutils'
|
24
|
+
Dir.mkdir('tmp') unless Dir.exist?('tmp')
|
25
|
+
FileUtils.cp('tasks/greenmat.rake', 'tmp')
|
26
|
+
|
27
|
+
sh 'git', 'checkout', '-B', target_merge_branch, target_branch
|
28
|
+
sh 'rake --rakefile tmp/greenmat.rake greenmat:rename_project'
|
29
|
+
sh 'git', 'add', '.'
|
30
|
+
sh 'git', 'commit', '--message', 'Rename project'
|
31
|
+
|
32
|
+
sh 'git', 'checkout', main_branch
|
33
|
+
sh 'git', 'merge', '--no-commit', '--strategy-option', 'theirs', target_merge_branch
|
34
|
+
end
|
6
35
|
end
|
7
36
|
|
8
37
|
module ProjectRenamer
|
@@ -22,7 +51,9 @@ module ProjectRenamer
|
|
22
51
|
/^tasks\//,
|
23
52
|
/^tmp\//,
|
24
53
|
/\.(?:bundle|so)$/,
|
25
|
-
/README
|
54
|
+
/README/,
|
55
|
+
/CHANGELOG.md/,
|
56
|
+
/CONTRIBUTING\.md/
|
26
57
|
]
|
27
58
|
|
28
59
|
module_function
|
data/test/custom_render_test.rb
CHANGED
@@ -10,7 +10,7 @@ class CustomRenderTest < Greenmat::TestCase
|
|
10
10
|
|
11
11
|
def test_simple_overload
|
12
12
|
md = Greenmat::Markdown.new(SimpleRender)
|
13
|
-
|
13
|
+
html_equal "<p>This is <em class=\"cool\">just</em> a test</p>\n",
|
14
14
|
md.render("This is *just* a test")
|
15
15
|
end
|
16
16
|
|
@@ -4,35 +4,35 @@ require 'test_helper'
|
|
4
4
|
class GreenmatCompatTest < Greenmat::TestCase
|
5
5
|
def test_simple_compat_api
|
6
6
|
html = GreenmatCompat.new("This is_just_a test").to_html
|
7
|
-
|
7
|
+
html_equal "<p>This is<em>just</em>a test</p>\n", html
|
8
8
|
end
|
9
9
|
|
10
10
|
def test_compat_api_enables_extensions
|
11
11
|
html = GreenmatCompat.new("This is_just_a test", :no_intra_emphasis).to_html
|
12
|
-
|
12
|
+
html_equal "<p>This is_just_a test</p>\n", html
|
13
13
|
end
|
14
14
|
|
15
15
|
def test_compat_api_knows_fenced_code_extension
|
16
16
|
text = "```ruby\nx = 'foo'\n```"
|
17
17
|
html = GreenmatCompat.new(text, :fenced_code).to_html
|
18
|
-
|
18
|
+
html_equal "<pre><code class=\"ruby\">x = 'foo'\n</code></pre>\n", html
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_compat_api_ignores_gh_blockcode_extension
|
22
22
|
text = "```ruby\nx = 'foo'\n```"
|
23
23
|
html = GreenmatCompat.new(text, :fenced_code, :gh_blockcode).to_html
|
24
|
-
|
24
|
+
html_equal "<pre><code class=\"ruby\">x = 'foo'\n</code></pre>\n", html
|
25
25
|
end
|
26
26
|
|
27
27
|
def test_compat_api_knows_no_intraemphasis_extension
|
28
28
|
html = GreenmatCompat.new("This is_just_a test", :no_intraemphasis).to_html
|
29
|
-
|
29
|
+
html_equal "<p>This is_just_a test</p>\n", html
|
30
30
|
end
|
31
31
|
|
32
32
|
def test_translate_outdated_extensions
|
33
33
|
# these extensions are no longer used
|
34
34
|
exts = [:gh_blockcode, :no_tables, :smart, :strict]
|
35
35
|
html = GreenmatCompat.new('"TEST"', *exts).to_html
|
36
|
-
|
36
|
+
html_equal "<p>"TEST"</p>\n", html
|
37
37
|
end
|
38
38
|
end
|
data/test/html_render_test.rb
CHANGED
@@ -3,7 +3,21 @@ require 'test_helper'
|
|
3
3
|
|
4
4
|
class HTMLRenderTest < Greenmat::TestCase
|
5
5
|
def setup
|
6
|
-
@
|
6
|
+
@markdown = Greenmat::Markdown.new(Greenmat::Render::HTML)
|
7
|
+
@rndr = {
|
8
|
+
:no_html => Greenmat::Render::HTML.new(:filter_html => true),
|
9
|
+
:no_images => Greenmat::Render::HTML.new(:no_images => true),
|
10
|
+
:no_links => Greenmat::Render::HTML.new(:no_links => true),
|
11
|
+
:safe_links => Greenmat::Render::HTML.new(:safe_links_only => true),
|
12
|
+
:escape_html => Greenmat::Render::HTML.new(:escape_html => true),
|
13
|
+
:hard_wrap => Greenmat::Render::HTML.new(:hard_wrap => true),
|
14
|
+
:toc_data => Greenmat::Render::HTML.new(:with_toc_data => true),
|
15
|
+
:prettify => Greenmat::Render::HTML.new(:prettify => true)
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def render_with(rndr, text)
|
20
|
+
Greenmat::Markdown.new(rndr).render(text)
|
7
21
|
end
|
8
22
|
|
9
23
|
# Hint: overrides filter_html, no_images and no_links
|
@@ -23,55 +37,45 @@ EOS
|
|
23
37
|
<p><img src="/favicon.ico" /></p>
|
24
38
|
EOE
|
25
39
|
|
26
|
-
|
40
|
+
markdown = render_with(@rndr[:escape_html], source)
|
41
|
+
html_equal expected, markdown
|
27
42
|
end
|
28
43
|
|
29
44
|
def test_that_filter_html_works
|
30
|
-
markdown = 'Through <em>NO</em> <script>DOUBLE NO</script>'
|
31
|
-
|
32
|
-
|
33
|
-
assert_equal "<p>Through NO DOUBLE NO</p>\n", output
|
45
|
+
markdown = render_with(@rndr[:no_html], 'Through <em>NO</em> <script>DOUBLE NO</script>')
|
46
|
+
html_equal "<p>Through NO DOUBLE NO</p>\n", markdown
|
34
47
|
end
|
35
48
|
|
36
49
|
def test_filter_html_doesnt_break_two_space_hard_break
|
37
|
-
markdown = "Lorem, \nipsum\n"
|
38
|
-
|
39
|
-
|
40
|
-
assert_equal "<p>Lorem,<br>\nipsum</p>\n", output
|
50
|
+
markdown = render_with(@rndr[:no_html], "Lorem, \nipsum\n")
|
51
|
+
html_equal "<p>Lorem,<br/>\nipsum</p>\n", markdown
|
41
52
|
end
|
42
53
|
|
43
54
|
def test_that_no_image_flag_works
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
assert_no_match %r{<img}, output
|
55
|
+
rd = render_with(@rndr[:no_images], %( <img src="image.png" />))
|
56
|
+
assert rd !~ /<img/
|
48
57
|
end
|
49
58
|
|
50
59
|
def test_that_no_links_flag_works
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
assert_no_match %r{<a }, output
|
60
|
+
rd = render_with(@rndr[:no_links], %([This link](http://example.net/) <a href="links.html">links</a>))
|
61
|
+
assert rd !~ /<a /
|
55
62
|
end
|
56
63
|
|
57
64
|
def test_that_safelink_flag_works
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
assert_equal "<p>[IRC](irc://chat.freenode.org/#freenode)</p>\n", output
|
65
|
+
rd = render_with(@rndr[:safe_links], "[IRC](irc://chat.freenode.org/#freenode)")
|
66
|
+
html_equal "<p>[IRC](irc://chat.freenode.org/#freenode)</p>\n", rd
|
62
67
|
end
|
63
68
|
|
64
69
|
def test_that_hard_wrap_works
|
65
|
-
|
70
|
+
rd = render_with(@rndr[:hard_wrap], <<EOE)
|
66
71
|
Hello world,
|
67
72
|
this is just a simple test
|
68
73
|
|
69
74
|
With hard wraps
|
70
75
|
and other *things*.
|
71
76
|
EOE
|
72
|
-
output = render(markdown, with: [:hard_wrap])
|
73
77
|
|
74
|
-
|
78
|
+
assert rd =~ /<br>/
|
75
79
|
end
|
76
80
|
|
77
81
|
def test_that_link_attributes_work
|
@@ -81,11 +85,11 @@ EOE
|
|
81
85
|
end
|
82
86
|
|
83
87
|
def test_that_link_works_with_quotes
|
84
|
-
|
85
|
-
|
88
|
+
rd = render_with(Greenmat::Render::HTML.new, %([This'link"is](http://example.net/)))
|
89
|
+
assert_equal "<p><a href=\"http://example.net/\">This'link"is</a></p>\n", rd
|
86
90
|
|
87
|
-
|
88
|
-
assert_equal
|
91
|
+
rd = render_with(@rndr[:escape_html], %([This'link"is](http://example.net/)))
|
92
|
+
assert_equal "<p><a href=\"http://example.net/\">This'link"is</a></p>\n", rd
|
89
93
|
end
|
90
94
|
|
91
95
|
def test_that_code_emphasis_work
|
@@ -107,19 +111,22 @@ However, this should be <em><code>an emphasised codespan</code></em></p>
|
|
107
111
|
</ul>
|
108
112
|
HTML
|
109
113
|
|
110
|
-
|
114
|
+
output = render_with(Greenmat::Render::HTML.new, markdown)
|
115
|
+
assert_equal html, output
|
111
116
|
end
|
112
117
|
|
113
118
|
def test_that_parenthesis_are_handled_into_links
|
114
|
-
markdown =
|
115
|
-
|
119
|
+
markdown = "Hey have a look at the [bash man page](man:bash(1))!"
|
120
|
+
html = "<p>Hey have a look at the <a href=\"man:bash(1)\">bash man page</a>!</p>\n"
|
121
|
+
output = render_with(Greenmat::Render::HTML.new, markdown)
|
116
122
|
|
117
|
-
assert_equal
|
123
|
+
assert_equal html, output
|
118
124
|
end
|
119
125
|
|
120
126
|
def test_autolinking_works_as_expected
|
121
|
-
markdown = "
|
122
|
-
|
127
|
+
markdown = "Example of uri ftp://user:pass@example.com/. Email foo@bar.com and link http://bar.com"
|
128
|
+
renderer = Greenmat::Markdown.new(Greenmat::Render::HTML, :autolink => true)
|
129
|
+
output = renderer.render(markdown)
|
123
130
|
|
124
131
|
assert output.include? '<a href="ftp://user:pass@example.com/">ftp://user:pass@example.com/</a>'
|
125
132
|
assert output.include? 'mailto:foo@bar.com'
|
@@ -148,7 +155,8 @@ MD
|
|
148
155
|
</div>
|
149
156
|
HTML
|
150
157
|
|
151
|
-
|
158
|
+
renderer = Greenmat::Markdown.new(Greenmat::Render::HTML, :footnotes => true)
|
159
|
+
output = renderer.render(markdown)
|
152
160
|
assert_equal html, output
|
153
161
|
end
|
154
162
|
|
@@ -164,78 +172,69 @@ MD
|
|
164
172
|
<p>[^1] And a trailing definition</p>
|
165
173
|
HTML
|
166
174
|
|
167
|
-
|
175
|
+
renderer = Greenmat::Markdown.new(Greenmat::Render::HTML, :footnotes => true)
|
176
|
+
output = renderer.render(markdown)
|
168
177
|
assert_equal html, output
|
169
178
|
end
|
170
179
|
|
171
180
|
def test_footnotes_enabled_but_missing_definition
|
172
181
|
markdown = "Some text with a marker[^1] but no definition."
|
173
|
-
|
182
|
+
html = "<p>Some text with a marker[^1] but no definition.</p>\n"
|
174
183
|
|
175
|
-
|
176
|
-
|
184
|
+
renderer = Greenmat::Markdown.new(Greenmat::Render::HTML, :footnotes => true)
|
185
|
+
output = renderer.render(markdown)
|
186
|
+
assert_equal html, output
|
177
187
|
end
|
178
188
|
|
179
189
|
def test_autolink_short_domains
|
180
190
|
markdown = "Example of uri ftp://auto/short/domains. Email auto@l.n and link http://a/u/t/o/s/h/o/r/t"
|
181
|
-
|
191
|
+
renderer = Greenmat::Markdown.new(Greenmat::Render::HTML, :autolink => true)
|
192
|
+
output = renderer.render(markdown)
|
182
193
|
|
183
194
|
assert output.include? '<a href="ftp://auto/short/domains">ftp://auto/short/domains</a>'
|
184
195
|
assert output.include? 'mailto:auto@l.n'
|
185
196
|
assert output.include? '<a href="http://a/u/t/o/s/h/o/r/t">http://a/u/t/o/s/h/o/r/t</a>'
|
186
197
|
end
|
187
198
|
|
188
|
-
def
|
189
|
-
markdown = "\
|
190
|
-
output
|
199
|
+
def test_toc_heading_id
|
200
|
+
markdown = "# First level heading\n## Second level heading"
|
201
|
+
output = render_with(@rndr[:toc_data], markdown)
|
202
|
+
assert_match /<h1 id="first-level-heading">/, output
|
203
|
+
assert_match /<h2 id="second-level-heading">/, output
|
204
|
+
end
|
191
205
|
|
192
|
-
|
206
|
+
def test_that_prettify_works
|
207
|
+
text = <<-Markdown
|
208
|
+
Foo
|
193
209
|
|
194
|
-
|
195
|
-
|
210
|
+
~~~ruby
|
211
|
+
some
|
212
|
+
code
|
213
|
+
~~~
|
196
214
|
|
197
|
-
|
198
|
-
|
215
|
+
Bar
|
216
|
+
Markdown
|
199
217
|
|
200
|
-
|
201
|
-
|
202
|
-
output = render(markdown, with: [:fenced_code_blocks, :prettify])
|
218
|
+
renderer = Greenmat::Markdown.new(@rndr[:prettify], fenced_code_blocks: true)
|
219
|
+
output = renderer.render(text)
|
203
220
|
|
204
|
-
assert output.include?("<code class=\"prettyprint
|
221
|
+
assert output.include?("<code class=\"prettyprint ruby\">")
|
205
222
|
end
|
206
223
|
|
207
224
|
def test_safe_links_only_with_anchors
|
208
225
|
markdown = "An [anchor link](#anchor) on a page."
|
209
|
-
|
226
|
+
|
227
|
+
renderer = Greenmat::Markdown.new(@rndr[:safe_links])
|
228
|
+
output = renderer.render(markdown)
|
210
229
|
|
211
230
|
assert_match %r{<a href="#anchor">anchor link</a>}, output
|
212
231
|
end
|
213
232
|
|
214
233
|
def test_autolink_with_link_attributes
|
215
|
-
|
216
|
-
|
234
|
+
render = Greenmat::Render::HTML.new(link_attributes: {rel: "nofollow"})
|
235
|
+
parser = Greenmat::Markdown.new(render, autolink: true)
|
217
236
|
|
237
|
+
output = parser.render("https://github.com/")
|
218
238
|
assert_match %r{rel="nofollow"}, output
|
219
239
|
end
|
220
|
-
|
221
|
-
def test_image_unsafe_src_with_safe_links_only
|
222
|
-
markdown = ";)"
|
223
|
-
output = render(markdown, with: [:safe_links_only])
|
224
|
-
|
225
|
-
assert_not_match %r{img src}, output
|
226
|
-
end
|
227
|
-
|
228
|
-
def test_no_styles_option_inside_a_paragraph
|
229
|
-
markdown = "Hello <style> foo { bar: baz; } </style> !"
|
230
|
-
output = render(markdown, with: [:no_styles])
|
231
|
-
|
232
|
-
assert_no_match %r{<style>}, output
|
233
|
-
end
|
234
|
-
|
235
|
-
def test_no_styles_inside_html_block_rendering
|
236
|
-
markdown = "<style> foo { bar: baz; } </style>"
|
237
|
-
output = render(markdown, with: [:no_styles])
|
238
|
-
|
239
|
-
assert_no_match %r{<style>}, output
|
240
|
-
end
|
241
240
|
end
|
@@ -3,12 +3,13 @@ require 'test_helper'
|
|
3
3
|
|
4
4
|
class HTMLTOCRenderTest < Greenmat::TestCase
|
5
5
|
def setup
|
6
|
-
@
|
6
|
+
@render = Greenmat::Render::HTML_TOC
|
7
7
|
@markdown = "# A title \n## A __nice__ subtitle\n## Another one \n### A sub-sub-title"
|
8
8
|
end
|
9
9
|
|
10
10
|
def test_simple_toc_render
|
11
|
-
|
11
|
+
renderer = Greenmat::Markdown.new(@render)
|
12
|
+
output = renderer.render(@markdown).strip
|
12
13
|
|
13
14
|
assert output.start_with?("<ul>")
|
14
15
|
assert output.end_with?("</ul>")
|
@@ -18,7 +19,8 @@ class HTMLTOCRenderTest < Greenmat::TestCase
|
|
18
19
|
end
|
19
20
|
|
20
21
|
def test_granular_toc_render
|
21
|
-
|
22
|
+
renderer = Greenmat::Markdown.new(@render.new(nesting_level: 2))
|
23
|
+
output = renderer.render(@markdown).strip
|
22
24
|
|
23
25
|
assert output.start_with?("<ul>")
|
24
26
|
assert output.end_with?("</ul>")
|
@@ -28,7 +30,8 @@ class HTMLTOCRenderTest < Greenmat::TestCase
|
|
28
30
|
end
|
29
31
|
|
30
32
|
def test_toc_heading_id
|
31
|
-
|
33
|
+
renderer = Greenmat::Markdown.new(@render)
|
34
|
+
output = renderer.render(@markdown)
|
32
35
|
|
33
36
|
assert_match /a-title/, output
|
34
37
|
assert_match /a-nice-subtitle/, output
|
@@ -37,40 +40,10 @@ class HTMLTOCRenderTest < Greenmat::TestCase
|
|
37
40
|
end
|
38
41
|
|
39
42
|
def test_toc_heading_with_hyphen_and_equal
|
40
|
-
|
43
|
+
renderer = Greenmat::Markdown.new(@render)
|
44
|
+
output = renderer.render("# Hello World\n\n-\n\n=")
|
41
45
|
|
42
46
|
assert_equal 1, output.scan("<li>").length
|
43
47
|
assert !output.include?('<a href=\"#\"></a>')
|
44
48
|
end
|
45
|
-
|
46
|
-
def test_anchor_generation_with_edge_cases
|
47
|
-
# Imported from ActiveSupport::Inflector#parameterize's tests
|
48
|
-
titles = {
|
49
|
-
"Donald E. Knuth" => "donald-e-knuth",
|
50
|
-
"Random text with *(bad)* characters" => "random-text-with-bad-characters",
|
51
|
-
"Trailing bad characters!@#" => "trailing-bad-characters",
|
52
|
-
"!@#Leading bad characters" => "leading-bad-characters",
|
53
|
-
"Squeeze separators" => "squeeze-separators",
|
54
|
-
"Test with + sign" => "test-with-sign",
|
55
|
-
"Test with a Namespaced::Class" => "test-with-a-namespaced-class"
|
56
|
-
}
|
57
|
-
|
58
|
-
titles.each do |title, anchor|
|
59
|
-
assert_match anchor, render("# #{title}")
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_inline_markup_is_not_escaped
|
64
|
-
output = render(@markdown)
|
65
|
-
|
66
|
-
assert_match "A <strong>nice</strong> subtitle", output
|
67
|
-
assert_no_match %r{<}, output
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_inline_markup_escaping
|
71
|
-
output = render(@markdown, with: [:escape_html])
|
72
|
-
|
73
|
-
assert_match "<strong>", output
|
74
|
-
assert_no_match %r{<strong>}, output
|
75
|
-
end
|
76
49
|
end
|