greenmat 3.2.0.2 → 3.2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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], %(![dust mite](http://dust.mite/image.png) <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 = "![foo](javascript:while(1);)"
|
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
|