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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +73 -0
- data/Rakefile +4 -0
- data/bin/minidown +33 -0
- data/lib/minidown.rb +13 -0
- data/lib/minidown/document.rb +142 -0
- data/lib/minidown/element.rb +40 -0
- data/lib/minidown/elements.rb +15 -0
- data/lib/minidown/elements/block_element.rb +37 -0
- data/lib/minidown/elements/code_block_element.rb +44 -0
- data/lib/minidown/elements/dividing_line_element.rb +11 -0
- data/lib/minidown/elements/html_element.rb +22 -0
- data/lib/minidown/elements/indent_code_element.rb +23 -0
- data/lib/minidown/elements/line_element.rb +28 -0
- data/lib/minidown/elements/list_element.rb +36 -0
- data/lib/minidown/elements/list_group_element.rb +87 -0
- data/lib/minidown/elements/order_list_element.rb +20 -0
- data/lib/minidown/elements/paragraph_element.rb +56 -0
- data/lib/minidown/elements/raw_html_element.rb +11 -0
- data/lib/minidown/elements/table_element.rb +80 -0
- data/lib/minidown/elements/text_element.rb +198 -0
- data/lib/minidown/elements/unorder_list_element.rb +31 -0
- data/lib/minidown/html_helper.rb +18 -0
- data/lib/minidown/parser.rb +19 -0
- data/lib/minidown/utils.rb +28 -0
- data/lib/minidown/version.rb +3 -0
- data/minidown.gemspec +26 -0
- data/spec/blank_line_spec.rb +21 -0
- data/spec/code_block_spec.rb +182 -0
- data/spec/dividing_line_spec.rb +35 -0
- data/spec/h1_and_h2_spec.rb +55 -0
- data/spec/indent_block_spec.rb +17 -0
- data/spec/li_spec.rb +354 -0
- data/spec/minidown_spec.rb +12 -0
- data/spec/paragraph_spec.rb +17 -0
- data/spec/raw_html_spec.rb +43 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/start_with_gt_spec.rb +70 -0
- data/spec/start_with_shape_spec.rb +42 -0
- data/spec/table_spec.rb +63 -0
- data/spec/task_list_spec.rb +18 -0
- data/spec/text_element_spec.rb +317 -0
- metadata +175 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
module Minidown
|
2
|
+
class HtmlElement < Element
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def initialize doc, content, name
|
6
|
+
super doc, content
|
7
|
+
@name = name
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse
|
11
|
+
nodes << self
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_html
|
15
|
+
build_tag @name do |tag|
|
16
|
+
# self.content is some Element
|
17
|
+
self.content = content.text if ParagraphElement === self.content
|
18
|
+
tag << self.content.to_html
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Minidown
|
2
|
+
class IndentCodeElement < Element
|
3
|
+
def initialize *_
|
4
|
+
super
|
5
|
+
@lines = [content]
|
6
|
+
end
|
7
|
+
|
8
|
+
def parse
|
9
|
+
while line = unparsed_lines.shift
|
10
|
+
case line
|
11
|
+
when Utils::Regexp[:indent_code]
|
12
|
+
@lines << $1
|
13
|
+
else
|
14
|
+
unparsed_lines.unshift line
|
15
|
+
break
|
16
|
+
end
|
17
|
+
end
|
18
|
+
unparsed_lines.unshift '```'
|
19
|
+
unparsed_lines.unshift *@lines
|
20
|
+
unparsed_lines.unshift '```'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Minidown
|
2
|
+
class LineElement < Element
|
3
|
+
attr_accessor :display
|
4
|
+
|
5
|
+
def initialize doc, content=nil
|
6
|
+
super
|
7
|
+
@display = true
|
8
|
+
end
|
9
|
+
|
10
|
+
def blank?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse
|
15
|
+
node = nodes.last
|
16
|
+
@display = (doc.within_block || TextElement === node)
|
17
|
+
nodes << self
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_html
|
21
|
+
if @display
|
22
|
+
br_tag
|
23
|
+
else
|
24
|
+
''
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Minidown
|
2
|
+
class ListElement < Element
|
3
|
+
attr_accessor :p_tag_content, :contents, :task_list, :checked
|
4
|
+
CheckedBox = '<input type="checkbox" class="task-list-item-checkbox" checked="" disabled="">'.freeze
|
5
|
+
UnCheckedBox = '<input type="checkbox" class="task-list-item-checkbox" disabled="">'.freeze
|
6
|
+
|
7
|
+
def initialize *_
|
8
|
+
super
|
9
|
+
@p_tag_content = false
|
10
|
+
@contents = [TextElement.new(doc, content)]
|
11
|
+
@task_list = false
|
12
|
+
@checked = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_html
|
16
|
+
@contents.map! do |content|
|
17
|
+
ParagraphElement === content ? content.text : content
|
18
|
+
end if @p_tag_content
|
19
|
+
content = list_content
|
20
|
+
content = build_tag('p'.freeze){|p| p << content} if @p_tag_content
|
21
|
+
attr = nil
|
22
|
+
attr = {class: 'task-list-item'.freeze} if @task_list
|
23
|
+
build_tag 'li'.freeze, attr do |li|
|
24
|
+
li << content
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def list_content
|
29
|
+
content = @contents.map(&:to_html).join(@p_tag_content ? br_tag : "\n".freeze)
|
30
|
+
if @task_list
|
31
|
+
content = (@checked ? CheckedBox : UnCheckedBox) + content
|
32
|
+
end
|
33
|
+
content
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Minidown
|
2
|
+
class ListGroupElement < Element
|
3
|
+
IndentRegexp = /\A\s{4,}(.+)/
|
4
|
+
StartWithBlankRegexp = /\A\s+(.+)/
|
5
|
+
|
6
|
+
attr_accessor :lists, :indent_level
|
7
|
+
|
8
|
+
def parse
|
9
|
+
nodes << self
|
10
|
+
while line = unparsed_lines.shift
|
11
|
+
#handle nested list
|
12
|
+
if (line =~ UnorderListElement::NestRegexp && list_class = UnorderListElement) || (line =~ OrderListElement::NestRegexp && list_class = OrderListElement)
|
13
|
+
li, str = $1.size, $2
|
14
|
+
if li > @indent_level
|
15
|
+
list_class.new(doc, str, li).parse
|
16
|
+
@lists.last.contents << nodes.pop
|
17
|
+
next
|
18
|
+
elsif li == @indent_level
|
19
|
+
list_class.new(doc, str, li).parse
|
20
|
+
child = nodes.pop
|
21
|
+
if LineElement === nodes.last
|
22
|
+
@lists.last.p_tag_content = child.lists.first.p_tag_content = true
|
23
|
+
end
|
24
|
+
if child.is_a?(ListGroupElement)
|
25
|
+
nodes.push *child.children
|
26
|
+
@lists.push *child.lists
|
27
|
+
else
|
28
|
+
@lists.last.contents << child
|
29
|
+
end
|
30
|
+
next
|
31
|
+
else
|
32
|
+
unparsed_lines.unshift line
|
33
|
+
break
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
doc.parse_line line
|
38
|
+
child = nodes.pop
|
39
|
+
case child
|
40
|
+
when self.class
|
41
|
+
if LineElement === nodes.last
|
42
|
+
@lists.last.p_tag_content = child.lists.first.p_tag_content = true
|
43
|
+
end
|
44
|
+
nodes.push *child.children
|
45
|
+
@lists.push *child.lists
|
46
|
+
break
|
47
|
+
when ParagraphElement
|
48
|
+
contents = @lists.last.contents
|
49
|
+
if line =~ StartWithBlankRegexp
|
50
|
+
doc.parse_line $1
|
51
|
+
node = nodes.pop
|
52
|
+
if TextElement === node || ParagraphElement === node
|
53
|
+
if TextElement === contents.last
|
54
|
+
contents.push(contents.pop.paragraph)
|
55
|
+
end
|
56
|
+
node = node.paragraph if TextElement === node
|
57
|
+
end
|
58
|
+
else
|
59
|
+
if @blank
|
60
|
+
unparsed_lines.unshift line
|
61
|
+
break
|
62
|
+
end
|
63
|
+
node = child.text
|
64
|
+
end
|
65
|
+
contents << node if node
|
66
|
+
when LineElement
|
67
|
+
next_line = unparsed_lines.first
|
68
|
+
if next_line.nil? || next_line.empty? || StartWithBlankRegexp === next_line || self.class.const_get(:ListRegexp) === next_line
|
69
|
+
child.display = false
|
70
|
+
nodes << child
|
71
|
+
else
|
72
|
+
unparsed_lines.unshift line
|
73
|
+
break
|
74
|
+
end
|
75
|
+
else
|
76
|
+
@put_back << child if child
|
77
|
+
break
|
78
|
+
end
|
79
|
+
@blank = (LineElement === child)
|
80
|
+
end
|
81
|
+
children_range = (nodes.index(self) + 1)..-1
|
82
|
+
children.push *nodes[children_range]
|
83
|
+
nodes[children_range] = []
|
84
|
+
nodes.push *@put_back
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Minidown
|
2
|
+
class OrderListElement < ListGroupElement
|
3
|
+
NestRegexp = /\A(\s*)\d+\.\s+(.+)/
|
4
|
+
ListRegexp = Minidown::Utils::Regexp[:order_list]
|
5
|
+
|
6
|
+
def initialize doc, line, indent_level = 0
|
7
|
+
super doc, line
|
8
|
+
@children << ListElement.new(doc, content)
|
9
|
+
@lists = @children.dup
|
10
|
+
@indent_level = indent_level
|
11
|
+
@put_back = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_html
|
15
|
+
build_tag 'ol'.freeze do |content|
|
16
|
+
children.each { |child| content << child.to_html}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Minidown
|
2
|
+
class ParagraphElement < Element
|
3
|
+
attr_reader :contents
|
4
|
+
attr_accessor :extra
|
5
|
+
|
6
|
+
ExcludeSchemeRegexp = /\A[^@:]+\z/
|
7
|
+
StringSymbolRegexp = /"|'/
|
8
|
+
|
9
|
+
def initialize *_
|
10
|
+
super
|
11
|
+
@contents = [raw_content]
|
12
|
+
@extra = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse
|
16
|
+
if ParagraphElement === nodes.last
|
17
|
+
nodes.last.contents << raw_content
|
18
|
+
else
|
19
|
+
nodes << self
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def text
|
24
|
+
build_element raw_content
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_html
|
28
|
+
if @extra
|
29
|
+
contents.map{|content| ParagraphElement.new(doc, content).to_html }.join ''.freeze
|
30
|
+
else
|
31
|
+
contents.map! do |line|
|
32
|
+
build_element line
|
33
|
+
end
|
34
|
+
build_tag 'p'.freeze do |content|
|
35
|
+
pre_elem = contents.shift
|
36
|
+
content << pre_elem.to_html
|
37
|
+
while elem = contents.shift
|
38
|
+
content << br_tag if TextElement === pre_elem && TextElement === elem
|
39
|
+
content << elem.to_html
|
40
|
+
pre_elem = elem
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def build_element content_str
|
49
|
+
if Utils::Regexp[:raw_html] =~ content_str && (raw = $1) && (ExcludeSchemeRegexp =~ raw || StringSymbolRegexp =~ raw)
|
50
|
+
RawHtmlElement.new doc, raw
|
51
|
+
else
|
52
|
+
TextElement.new doc, content_str
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
module Minidown
|
2
|
+
class TableElement < Element
|
3
|
+
AlignSpecRegexp = /\A\|?\s*([\-:]\-+[\-:]\s*(?:\|\s*[\-:]\-+[\-:]\s*)*)\|?\s*\z/
|
4
|
+
|
5
|
+
def initialize doc, content, raw_head
|
6
|
+
super doc, content
|
7
|
+
@raw_head = raw_head
|
8
|
+
@heads = @raw_head.split('|'.freeze).map! &:strip
|
9
|
+
@column_count = @heads.count
|
10
|
+
end
|
11
|
+
|
12
|
+
def check_column_spec raw_column_spec
|
13
|
+
if @valid.nil?
|
14
|
+
@valid = Utils::Regexp[:pipe_symbol] =~ raw_column_spec && AlignSpecRegexp =~ raw_column_spec && (column_spec_str = $1) && (@column_specs = column_spec_str.split('|'.freeze).map! &:strip) && @column_specs.count == @column_count
|
15
|
+
else
|
16
|
+
@valid
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse
|
21
|
+
if @valid
|
22
|
+
nodes << self
|
23
|
+
@bodys = []
|
24
|
+
@column_specs.map! do |column_spec|
|
25
|
+
if column_spec[0] == column_spec[-1]
|
26
|
+
column_spec[0] == ':'.freeze ? 'center'.freeze : nil
|
27
|
+
else
|
28
|
+
column_spec[0] == ':'.freeze ? 'left'.freeze : 'right'.freeze
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
while line = unparsed_lines.shift
|
33
|
+
if Utils::Regexp[:table] =~ line && (cells = $1.split('|'.freeze).map! &:strip) && @column_count == cells.count
|
34
|
+
@bodys << cells
|
35
|
+
else
|
36
|
+
unparsed_lines.unshift line
|
37
|
+
break
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
raise 'table column specs not valid'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_html
|
46
|
+
attrs = @column_specs.map do |align|
|
47
|
+
{align: align}.freeze if align
|
48
|
+
end
|
49
|
+
build_tag 'table'.freeze do |table|
|
50
|
+
thead = build_tag 'thead'.freeze do |thead|
|
51
|
+
tr = build_tag 'tr'.freeze do |tr|
|
52
|
+
@heads.each_with_index do |cell, i|
|
53
|
+
th = build_tag 'th'.freeze, attrs[i] do |th|
|
54
|
+
th << cell
|
55
|
+
end
|
56
|
+
tr << th
|
57
|
+
end
|
58
|
+
end
|
59
|
+
thead << tr
|
60
|
+
end
|
61
|
+
table << thead
|
62
|
+
|
63
|
+
tbody = build_tag 'tbody'.freeze do |tbody|
|
64
|
+
@bodys.each do |row|
|
65
|
+
tr = build_tag 'tr'.freeze do |tr|
|
66
|
+
row.each_with_index do |cell, i|
|
67
|
+
td = build_tag 'td'.freeze, attrs[i] do |td|
|
68
|
+
td << TextElement.new(doc, cell).to_html
|
69
|
+
end
|
70
|
+
tr << td
|
71
|
+
end
|
72
|
+
end
|
73
|
+
tbody << tr
|
74
|
+
end
|
75
|
+
end
|
76
|
+
table << tbody
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
module Minidown
|
2
|
+
class TextElement < Element
|
3
|
+
EscapeChars = %w{# > * + \- ` _ { } ( ) . ! \[ \] ~}
|
4
|
+
EscapeRegexp = /(?<!\\)\\([#{EscapeChars.join '|'}|\\])/
|
5
|
+
|
6
|
+
Regexp = {
|
7
|
+
tag: /(\\*)<(.+?)(\\*)>/,
|
8
|
+
quot: /"/,
|
9
|
+
link: /(?<!\!)\[(.+?)\]\((.+?)\)/,
|
10
|
+
link_title: /((?<=").+?(?="))/,
|
11
|
+
link_url: /(\S+)/,
|
12
|
+
link_ref: /(?<!\!)\[(.+?)\]\s*\[(.*?)\]/,
|
13
|
+
image: /\!\[(.+?)\]\((.+?)\)/,
|
14
|
+
image_ref: /\!\[(.+?)\]\s*\[(.*?)\]/,
|
15
|
+
star: /((?<!\\)\*{1,2})(.+?)\1/,
|
16
|
+
underline: /(?<=\A|\s)((?<!\\)\_{1,2})(\S+)\1(?=\z|\s)/,
|
17
|
+
delete_line: /(?<!\\)~~(?!\s)(.+?)(?<!\s)~~/,
|
18
|
+
quotlink: /\<(.+?)\>/,
|
19
|
+
link_scheme: /\A\S+?\:\/\//,
|
20
|
+
email: /\A[A-Za-z0-9]+@[A-Za-z0-9]+\.[A-Za-z0-9]+/,
|
21
|
+
auto_email: /(?<!\S)[A-Za-z0-9]+@[A-Za-z0-9]+\.[A-Za-z0-9]+(?!\S)/,
|
22
|
+
auto_link: /(?<!\S)\w+?\:\/\/.+?(?!\S)/,
|
23
|
+
inline_code: /(?<!\\)(`+)\s*(.+?)\s*(?<!\\)\1/
|
24
|
+
}.freeze
|
25
|
+
|
26
|
+
attr_accessor :escape, :convert, :sanitize
|
27
|
+
|
28
|
+
def initialize *_
|
29
|
+
super
|
30
|
+
@escape = true
|
31
|
+
@sanitize = false
|
32
|
+
@convert = true
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse
|
36
|
+
nodes << self
|
37
|
+
end
|
38
|
+
|
39
|
+
def content
|
40
|
+
str = super
|
41
|
+
str = convert_str(str) if convert
|
42
|
+
escape_content! str
|
43
|
+
escape_str! str
|
44
|
+
escape_html str if sanitize
|
45
|
+
str
|
46
|
+
end
|
47
|
+
|
48
|
+
def escape_str! str
|
49
|
+
str.gsub!(EscapeRegexp, '\\1'.freeze) if escape
|
50
|
+
end
|
51
|
+
|
52
|
+
def escape_html str
|
53
|
+
str.replace Utils.escape_html(str)
|
54
|
+
end
|
55
|
+
|
56
|
+
def escape_content! str
|
57
|
+
return str unless @escape
|
58
|
+
escape_html str
|
59
|
+
|
60
|
+
str.gsub! Regexp[:tag] do
|
61
|
+
left, tag, right = $1, $2, $3
|
62
|
+
tag.gsub! Regexp[:quot] do
|
63
|
+
'"'.freeze
|
64
|
+
end
|
65
|
+
|
66
|
+
left = left.size.odd? ? "#{left[0..-2]}<" : "#{left}<" if left
|
67
|
+
left ||= "<".freeze
|
68
|
+
|
69
|
+
right = right.size.odd? ? "#{right[0..-2]}>" : "#{right}>" if right
|
70
|
+
right ||= ">".freeze
|
71
|
+
|
72
|
+
"#{left}#{tag}#{right}"
|
73
|
+
end
|
74
|
+
str
|
75
|
+
end
|
76
|
+
|
77
|
+
def convert_str str
|
78
|
+
#auto link
|
79
|
+
str.gsub! Regexp[:auto_link] do |origin_str|
|
80
|
+
build_tag 'a'.freeze, href: origin_str do |a|
|
81
|
+
a << origin_str
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
#auto email
|
86
|
+
str.gsub! Regexp[:auto_email] do |origin_str|
|
87
|
+
build_tag 'a'.freeze, href: "mailto:#{origin_str}" do |a|
|
88
|
+
a << origin_str
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#parse <link>
|
93
|
+
str.gsub! Regexp[:quotlink] do |origin_str|
|
94
|
+
link = $1
|
95
|
+
attr = case link
|
96
|
+
when Regexp[:link_scheme]
|
97
|
+
{href: link}
|
98
|
+
when Regexp[:email]
|
99
|
+
{href: "mailto:#{link}"}
|
100
|
+
end
|
101
|
+
attr ? build_tag('a'.freeze, attr){|a| a << link} : origin_str
|
102
|
+
end
|
103
|
+
|
104
|
+
#parse * _
|
105
|
+
Regexp.values_at(:star, :underline).each do |regex|
|
106
|
+
str.gsub! regex do |origin_str|
|
107
|
+
tag_name = $1.size > 1 ? 'strong'.freeze : 'em'.freeze
|
108
|
+
build_tag tag_name do |tag|
|
109
|
+
tag << $2
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
#parse ~~del~~
|
115
|
+
str.gsub! Regexp[:delete_line] do |origin_str|
|
116
|
+
build_tag 'del'.freeze do |tag|
|
117
|
+
tag << $1
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
#convert image reference
|
122
|
+
str.gsub! Regexp[:image_ref] do |origin_str|
|
123
|
+
alt = $1
|
124
|
+
id = ($2 && !$2.empty?) ? $2 : $1
|
125
|
+
ref = doc.links_ref[id.downcase]
|
126
|
+
if ref
|
127
|
+
attr = {src: ref[:url], alt: alt}
|
128
|
+
attr[:title] = ref[:title] if ref[:title] && !ref[:title].empty?
|
129
|
+
build_tag 'img'.freeze, attr
|
130
|
+
else
|
131
|
+
origin_str
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
#convert image syntax
|
136
|
+
str.gsub! Regexp[:image] do
|
137
|
+
alt, url = $1, $2
|
138
|
+
url =~ Regexp[:link_title]
|
139
|
+
title = $1
|
140
|
+
url =~ Regexp[:link_url]
|
141
|
+
url = $1
|
142
|
+
attr = {src: url, alt: alt}
|
143
|
+
attr[:title] = title if title
|
144
|
+
build_tag 'img'.freeze, attr
|
145
|
+
end
|
146
|
+
|
147
|
+
#convert link reference
|
148
|
+
str.gsub! Regexp[:link_ref] do |origin_str|
|
149
|
+
text = $1
|
150
|
+
id = ($2 && !$2.empty?) ? $2 : $1
|
151
|
+
ref = doc.links_ref[id.downcase]
|
152
|
+
if ref
|
153
|
+
attr = {href: ref[:url]}
|
154
|
+
attr[:title] = ref[:title] if ref[:title] && !ref[:title].empty?
|
155
|
+
build_tag 'a'.freeze, attr do |a|
|
156
|
+
a << text
|
157
|
+
end
|
158
|
+
else
|
159
|
+
origin_str
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
#convert link syntax
|
164
|
+
str.gsub! Regexp[:link] do
|
165
|
+
text, url = $1, $2
|
166
|
+
url =~ Regexp[:link_title]
|
167
|
+
title = $1
|
168
|
+
url =~ Regexp[:link_url]
|
169
|
+
url = $1
|
170
|
+
attr = {href: url}
|
171
|
+
attr[:title] = title if title
|
172
|
+
build_tag 'a'.freeze, attr do |content|
|
173
|
+
content << text
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
escape_content! str
|
178
|
+
|
179
|
+
#inline code
|
180
|
+
str.gsub! Regexp[:inline_code] do |origin_str|
|
181
|
+
build_tag 'code'.freeze do |code|
|
182
|
+
code << escape_html($2)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
escape_str! str
|
186
|
+
@escape = false
|
187
|
+
str
|
188
|
+
end
|
189
|
+
|
190
|
+
def paragraph
|
191
|
+
ParagraphElement.new doc, raw_content
|
192
|
+
end
|
193
|
+
|
194
|
+
def to_html
|
195
|
+
content
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|