minidown 2.1.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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +9 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +73 -0
  7. data/Rakefile +4 -0
  8. data/bin/minidown +33 -0
  9. data/lib/minidown.rb +13 -0
  10. data/lib/minidown/document.rb +142 -0
  11. data/lib/minidown/element.rb +40 -0
  12. data/lib/minidown/elements.rb +15 -0
  13. data/lib/minidown/elements/block_element.rb +37 -0
  14. data/lib/minidown/elements/code_block_element.rb +44 -0
  15. data/lib/minidown/elements/dividing_line_element.rb +11 -0
  16. data/lib/minidown/elements/html_element.rb +22 -0
  17. data/lib/minidown/elements/indent_code_element.rb +23 -0
  18. data/lib/minidown/elements/line_element.rb +28 -0
  19. data/lib/minidown/elements/list_element.rb +36 -0
  20. data/lib/minidown/elements/list_group_element.rb +87 -0
  21. data/lib/minidown/elements/order_list_element.rb +20 -0
  22. data/lib/minidown/elements/paragraph_element.rb +56 -0
  23. data/lib/minidown/elements/raw_html_element.rb +11 -0
  24. data/lib/minidown/elements/table_element.rb +80 -0
  25. data/lib/minidown/elements/text_element.rb +198 -0
  26. data/lib/minidown/elements/unorder_list_element.rb +31 -0
  27. data/lib/minidown/html_helper.rb +18 -0
  28. data/lib/minidown/parser.rb +19 -0
  29. data/lib/minidown/utils.rb +28 -0
  30. data/lib/minidown/version.rb +3 -0
  31. data/minidown.gemspec +26 -0
  32. data/spec/blank_line_spec.rb +21 -0
  33. data/spec/code_block_spec.rb +182 -0
  34. data/spec/dividing_line_spec.rb +35 -0
  35. data/spec/h1_and_h2_spec.rb +55 -0
  36. data/spec/indent_block_spec.rb +17 -0
  37. data/spec/li_spec.rb +354 -0
  38. data/spec/minidown_spec.rb +12 -0
  39. data/spec/paragraph_spec.rb +17 -0
  40. data/spec/raw_html_spec.rb +43 -0
  41. data/spec/spec_helper.rb +2 -0
  42. data/spec/start_with_gt_spec.rb +70 -0
  43. data/spec/start_with_shape_spec.rb +42 -0
  44. data/spec/table_spec.rb +63 -0
  45. data/spec/task_list_spec.rb +18 -0
  46. data/spec/text_element_spec.rb +317 -0
  47. metadata +175 -0
@@ -0,0 +1,31 @@
1
+ module Minidown
2
+ class UnorderListElement < ListGroupElement
3
+ TaskRegexp = /\A\[([ x])\](.+)/
4
+ NestRegexp = /\A(\s*)[*\-+]\s+(.+)/
5
+ ListRegexp = Minidown::Utils::Regexp[:unorder_list]
6
+
7
+ def initialize doc, line, indent_level = 0
8
+ super doc, line
9
+ if content =~ TaskRegexp
10
+ @task_ul ||= true
11
+ list = ListElement.new(doc, $2)
12
+ list.task_list = true
13
+ list.checked = ($1 == 'x'.freeze)
14
+ else
15
+ list = ListElement.new(doc, content)
16
+ end
17
+ @children << list
18
+ @lists = @children.dup
19
+ @indent_level = indent_level
20
+ @put_back = []
21
+ end
22
+
23
+ def to_html
24
+ attr = nil
25
+ attr = {class: 'task-list'.freeze} if @task_ul
26
+ build_tag 'ul'.freeze, attr do |content|
27
+ children.each { |child| content << child.to_html}
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ module Minidown
2
+ module HtmlHelper
3
+ def build_tag name, attr = nil
4
+ content = ''
5
+ yield content if block_given?
6
+ if attr
7
+ attr = attr.map{|k, v| "#{k}=\"#{v}\""}.join ' '.freeze
8
+ "<#{name} #{attr}>#{content}</#{name}>"
9
+ else
10
+ "<#{name}>#{content}</#{name}>"
11
+ end
12
+ end
13
+
14
+ def br_tag
15
+ '<br>'
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ module Minidown
2
+ class Parser
3
+ def initialize options = {}
4
+ @options = options.freeze
5
+ end
6
+
7
+ def render str
8
+ parse(str).to_html
9
+ end
10
+
11
+ protected
12
+ def parse str
13
+ lines = str.split Utils::Regexp[:lines]
14
+ doc = Document.new lines, @options
15
+ doc.parse
16
+ doc
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ module Minidown
2
+ module Utils
3
+ Regexp = {
4
+ lines: /\n|\r\n/,
5
+ blank_line: /\A\s*\z/,
6
+ raw_html: /\A\s*(\<(?=[^\<\>]).+(?<=[^\<\>])\>)*\s*\z/,
7
+ h1_or_h2: /\A([=-]{3,})(.*)/,
8
+ start_with_shape: /\A(\#{1,6})\s*(.+?)\s*#*\z/,
9
+ start_with_quote: /\A\>\s*(.+)/,
10
+ unorder_list: /\A(\s*)[*\-+]\s+(.+)/,
11
+ order_list: /\A(\s*)\d+\.\s+(.+)/,
12
+ code_block: /\A\s*[`~]{3,}\s*(\S*)/,
13
+ table: /\A\|?([^\|]+(?:\|[^\|]*)*)\|?\s*\z/,
14
+ dividing_line: /\A(\s*[*-]\s*){3,}\z/,
15
+ indent_code: /\A\s{4}(.+)/,
16
+ pipe_symbol: /\|/
17
+ }.freeze
18
+
19
+ class << self
20
+ def escape_html str
21
+ sanitized_str = str.dup
22
+ sanitized_str.gsub! "<".freeze, "&lt;".freeze
23
+ sanitized_str.gsub! ">".freeze, "&gt;".freeze
24
+ sanitized_str
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module Minidown
2
+ VERSION = "2.1.1"
3
+ end
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'minidown/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "minidown"
8
+ spec.version = Minidown::VERSION
9
+ spec.authors = ["jjy"]
10
+ spec.email = ["jjyruby@gmail.com"]
11
+ spec.description = %q{Minidown is a lightweight & fast markdown parser, with complete GFM support.}
12
+ spec.summary = %q{Minidown is a lightweight & fast markdown parser, with complete GFM support.}
13
+ spec.homepage = "https://github.com/jjyr/minidown"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "pry"
25
+ spec.add_development_dependency "pry-nav"
26
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Minidown do
4
+ describe 'blank line' do
5
+ it 'should parse as nothing' do
6
+ ['', "\n", "\n\n", "\n\n\n\n"].each do |str|
7
+ Minidown.render(str).should == ''
8
+ end
9
+ end
10
+
11
+ it 'should be ignore when blank is the first line' do
12
+ str = "\na"
13
+ Minidown.render(str).should == "<p>a</p>"
14
+ str = "\n\n h"
15
+ Minidown.render(str).should == "<p> h</p>"
16
+ ["\n \n", "\n \n\n\n"].each do |str|
17
+ Minidown.render(str).should == "#{str.split(Minidown::Utils::Regexp[:lines]).last}".strip
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,182 @@
1
+ require 'spec_helper'
2
+
3
+ describe Minidown do
4
+ describe 'code_block' do
5
+ it 'should parse correct' do
6
+ str =<<HERE
7
+ ```
8
+ should in code block
9
+
10
+ in block
11
+ ```
12
+ HERE
13
+ Minidown.render(str).should == "<pre><code>should in code block\n\nin block</code></pre>"
14
+ end
15
+
16
+ it 'should allow tildes as well as backquotes' do
17
+ str =<<HERE
18
+ ~~~
19
+ should in code block
20
+
21
+ in block
22
+ ~~~
23
+ HERE
24
+ Minidown.render(str).should == "<pre><code>should in code block\n\nin block</code></pre>"
25
+ end
26
+
27
+ it 'should allow arbitrary number of `' do
28
+ str =<<HERE
29
+ ````````````
30
+ should in code block
31
+
32
+ in block
33
+ ````````````
34
+ HERE
35
+ Minidown.render(str).should == "<pre><code>should in code block\n\nin block</code></pre>"
36
+ end
37
+
38
+ it 'should allow arbitrary number of tildes' do
39
+ str =<<HERE
40
+ ~~~~~~~~~~~
41
+ should in code block
42
+
43
+ in block
44
+ ~~~~~~~~~~~
45
+ HERE
46
+ Minidown.render(str).should == "<pre><code>should in code block\n\nin block</code></pre>"
47
+ end
48
+
49
+
50
+ it 'should ignore space' do
51
+ str =<<HERE
52
+ ```
53
+ should in code block
54
+ in block
55
+ ```
56
+ HERE
57
+ Minidown.render(str).should == "<pre><code>should in code block\nin block</code></pre>"
58
+ end
59
+
60
+ it 'should have lang attribute' do
61
+ str =<<HERE
62
+ ``` ruby
63
+ should in code block
64
+
65
+ in block
66
+ ```
67
+ HERE
68
+ Minidown.render(str).should == "<pre><code class=\"ruby\">should in code block\n\nin block</code></pre>"
69
+ end
70
+
71
+ it 'should have lang attribute with tildes' do
72
+ str =<<HERE
73
+ ~~~ ruby
74
+ should in code block
75
+
76
+ in block
77
+ ~~~
78
+ HERE
79
+ Minidown.render(str).should == "<pre><code class=\"ruby\">should in code block\n\nin block</code></pre>"
80
+ end
81
+
82
+ it 'should allow escape' do
83
+ str =<<HERE
84
+ \\```
85
+ should in code block
86
+
87
+ in block
88
+ \\```
89
+ HERE
90
+ Minidown.render(str).should == "<p>```<br>should in code block</p><p>in block<br>```</p>"
91
+ str =<<HERE
92
+ \\~~~
93
+ should in code block
94
+
95
+ in block
96
+ \\~~~
97
+ HERE
98
+ Minidown.render(str).should == "<p>~~~<br>should in code block</p><p>in block<br>~~~</p>"
99
+ end
100
+
101
+ it 'should not escape content' do
102
+ str =<<HERE
103
+ ```
104
+ \\+
105
+ \\.
106
+ \\-
107
+ \\*
108
+ <>
109
+ ```
110
+ HERE
111
+ Minidown.render(str).should == "<pre><code>\\+\n\\.\n\\-\n\\*\n&lt;&gt;</code></pre>"
112
+ str =<<HERE
113
+ ~~~
114
+ \\+
115
+ \\.
116
+ \\-
117
+ \\*
118
+ <>
119
+ ~~~
120
+ HERE
121
+ Minidown.render(str).should == "<pre><code>\\+\n\\.\n\\-\n\\*\n&lt;&gt;</code></pre>"
122
+ end
123
+
124
+ it 'should escape html tag' do
125
+ str ='```
126
+ <a>hello</a>
127
+ ```'
128
+ Minidown.render(str).should == "<pre><code>&lt;a&gt;hello&lt;/a&gt;</code></pre>"
129
+ str ='~~~
130
+ <a>hello</a>
131
+ ~~~'
132
+ Minidown.render(str).should == "<pre><code>&lt;a&gt;hello&lt;/a&gt;</code></pre>"
133
+ end
134
+
135
+ it 'should not auto convert' do
136
+ str = '```
137
+ jjyruby@gmail.com
138
+ ```'
139
+ Minidown.render(str).should == '<pre><code>jjyruby@gmail.com</code></pre>'
140
+ str = '~~~
141
+ jjyruby@gmail.com
142
+ ~~~'
143
+ Minidown.render(str).should == '<pre><code>jjyruby@gmail.com</code></pre>'
144
+ end
145
+
146
+ describe "work with code block handler" do
147
+ it "work with handler" do
148
+ str = '``` ruby
149
+ puts "We love ruby!"
150
+ ```'
151
+ handler = ->(lang, content){"`#{content}` is write in #{lang}"}
152
+ Minidown.render(str, code_block_handler: handler).should == '`puts "We love ruby!"` is write in ruby'
153
+ end
154
+
155
+ it "lang should return empty if not specific language" do
156
+ str = '```
157
+ not specific language
158
+ ```'
159
+ handler = ->(lang, content){ "#{content}, so lang is #{lang.inspect}" }
160
+ Minidown.render(str, code_block_handler: handler).should == 'not specific language, so lang is nil'
161
+ end
162
+
163
+ it "handler should pass raw content" do
164
+ str = '```
165
+ <script>
166
+ ```'
167
+ handler = ->(lang, content){ content.gsub("<", "{").gsub(">", "}") }
168
+ Minidown.render(str, code_block_handler: handler).should == '{script}'
169
+ end
170
+
171
+ it "should not escape <>" do
172
+ test_cases = %w{<script> <> < >}
173
+ handler = ->(lang, content){ content }
174
+ parser = Minidown::Parser.new(code_block_handler: handler)
175
+ test_cases.each do |case_s|
176
+ str = "```\n#{case_s}\n```"
177
+ parser.render(str).should == case_s
178
+ end
179
+ end
180
+ end
181
+ end
182
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Minidown do
4
+ describe 'dividing line' do
5
+ it 'parsed correct' do
6
+ str = '***'
7
+ Minidown.render(str).should == '<hr>'
8
+ str = '---'
9
+ Minidown.render(str).should == '<hr>'
10
+ str = ' *** '
11
+ Minidown.render(str).should == '<hr>'
12
+ str = ' * * * '
13
+ Minidown.render(str).should == '<hr>'
14
+ str = ' -- - '
15
+ Minidown.render(str).should == '<hr>'
16
+ str = '----'
17
+ Minidown.render(str).should == '<hr>'
18
+ end
19
+
20
+ it 'should not parse if any other character' do
21
+ str = 'f---'
22
+ Minidown.render(str).should == '<p>f---</p>'
23
+
24
+ str = '* * *z'
25
+ Minidown.render(str).should == '<ul><li><em> </em>z</li></ul>'
26
+ end
27
+
28
+ it 'should allow escape' do
29
+ str = "\\----"
30
+ Minidown.render(str).should == '<p>----</p>'
31
+ str = "\\* * *"
32
+ Minidown.render(str).should == '<p>* <em> </em></p>'
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Minidown do
4
+ describe '======== or -------' do
5
+ it 'should parse as text' do
6
+ %w{===== =====hello ------nihao}.each do |str|
7
+ Minidown.render(str).should == "<p>#{str}</p>"
8
+ end
9
+ end
10
+
11
+ it 'should parse as h1' do
12
+ %w{======= ==== === = ==}.each do |s|
13
+ str =<<HERE
14
+ h1
15
+ #{s}
16
+ HERE
17
+ if s.size < 3
18
+ Minidown.render(str).should == "<p>h1<br>#{s}</p>"
19
+ else
20
+ Minidown.render(str).should == "<h1>h1</h1>"
21
+ end
22
+ end
23
+ end
24
+
25
+ it 'should parse as h2' do
26
+ %w{------- ---- --- - --}.each do |s|
27
+ str =<<HERE
28
+ h2
29
+ #{s}
30
+ HERE
31
+ if s.size < 3
32
+ Minidown.render(str).should == "<p>h2<br>#{s}</p>"
33
+ else
34
+ Minidown.render(str).should == "<h2>h2</h2>"
35
+ end
36
+ end
37
+ end
38
+
39
+ it 'should parse newtext' do
40
+ %w{------ =======}.each do |s|
41
+ str =<<HERE
42
+ title
43
+ #{s}should show text
44
+ HERE
45
+ tag = (s[0] == '-' ? 'h2' : 'h1')
46
+ Minidown.render(str).should == "<#{tag}>title</#{tag}><p>should show text</p>"
47
+ end
48
+ end
49
+
50
+ it 'should not parse as h2 if preline is h tag' do
51
+ str = "#### [ruby](http://ruby-lang.org/)\n---"
52
+ Minidown.render(str).should == "<h4><a href=\"http://ruby-lang.org/\">ruby</a></h4><hr>"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Minidown do
4
+ describe 'indent should parse as code block' do
5
+ it 'should parse correct' do
6
+ str =<<HERE
7
+ Here is a Python code example
8
+ without syntax highlighting:
9
+
10
+ def foo:
11
+ if not bar:
12
+ return true
13
+ HERE
14
+ Minidown.render(str).should == "<p>Here is a Python code example<br>without syntax highlighting:</p><pre><code>def foo:\n if not bar:\n return true</code></pre>"
15
+ end
16
+ end
17
+ end