daimon_markdown 0.6.0 → 0.7.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/README.md +8 -4
- data/lib/daimon_markdown/filter/plugin.rb +14 -0
- data/lib/daimon_markdown/plugin.rb +3 -0
- data/lib/daimon_markdown/plugin/toc.rb +114 -35
- data/lib/daimon_markdown/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1b919648b289fa4707eb5d83c1543de90eb49add
|
4
|
+
data.tar.gz: 15f05ea47e81dfd6ec438426dc7290cabae176e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd11bfa96af73ce7d7de20d6678aaa2548fac1bdd72e94a36fa5ad2ba8792421a79af41030784cdc0bfca35f464c0955683c19df6bfce3fcbc8c59246e669352
|
7
|
+
data.tar.gz: 250dcf44e7b67d2d3fa57bffa124d85b6fc0eb4ed6e8db485fb1f4ff759da28cac87cc050f25ebdeb44aea55610981b9a55865d2c76b0de16a8987482e332e81
|
data/README.md
CHANGED
@@ -22,12 +22,16 @@ Or install it yourself as:
|
|
22
22
|
|
23
23
|
## Usage
|
24
24
|
|
25
|
-
|
25
|
+
For example, in your Rails application:
|
26
26
|
|
27
27
|
```ruby
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
module MarkdownHelper
|
29
|
+
def render_markdown(markdown_text, context = {})
|
30
|
+
processor = DaimonMarkdown::Processor.new(context)
|
31
|
+
result = processor.call(markdown_text)
|
32
|
+
puts result[:output].to_s.html_safe
|
33
|
+
end
|
34
|
+
end
|
31
35
|
```
|
32
36
|
|
33
37
|
## How to write plugin
|
@@ -19,6 +19,20 @@ module DaimonMarkdown
|
|
19
19
|
node.replace(message)
|
20
20
|
rescue DaimonMarkdown::Plugin::UnknownPluginError => ex
|
21
21
|
node.replace(ex.message)
|
22
|
+
rescue DaimonMarkdown::Plugin::Error => ex
|
23
|
+
message = <<~MESSAGE
|
24
|
+
<pre>Error occured in #{plugin_class}
|
25
|
+
#{node} (#{ex.class}: #{ex.message})
|
26
|
+
#{ex.backtrace.join("\n")}</pre>
|
27
|
+
MESSAGE
|
28
|
+
node.parent.replace(message)
|
29
|
+
rescue => ex
|
30
|
+
message = <<~MESSAGE
|
31
|
+
<pre>Unexpected error occured in #{plugin_class}
|
32
|
+
#{node} (#{ex.class}: #{ex.message})
|
33
|
+
#{ex.backtrace.join("\n")}</pre>
|
34
|
+
MESSAGE
|
35
|
+
node.parent.replace(message)
|
22
36
|
end
|
23
37
|
end
|
24
38
|
unless result[:plugins].empty?
|
@@ -5,55 +5,134 @@ module DaimonMarkdown
|
|
5
5
|
|
6
6
|
def call(limit = nil)
|
7
7
|
toc_html = ""
|
8
|
-
|
8
|
+
toc_class = context[:toc_class] || "section-nav"
|
9
9
|
|
10
|
-
|
10
|
+
ul_list = Hash.new {|h, k| h[k] = UnorderedList.new }
|
11
|
+
ul_list[1] = UnorderedList.new(html_class: toc_class)
|
11
12
|
previous_level = 1
|
12
13
|
doc.css("h1, h2, h3, h4, h5, h6").each do |header_node|
|
13
|
-
|
14
|
-
next if limit && limit < level
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
if headers[id] > 0
|
21
|
-
unique_id = "#{id}-#{headers[id]}"
|
22
|
-
else
|
23
|
-
unique_id = id
|
24
|
-
end
|
25
|
-
headers[id] += 1
|
26
|
-
header_content = header_node.children.first
|
27
|
-
# TODO: Arrange indent level
|
28
|
-
if header_content
|
29
|
-
diff = level - previous_level
|
30
|
-
case
|
31
|
-
when diff > 0
|
32
|
-
items.concat(["<ul>"] * diff)
|
33
|
-
when diff < 0
|
34
|
-
items.concat(["</ul>"] * diff.abs)
|
14
|
+
header = Header.new(header_node)
|
15
|
+
next if limit && limit < header.level
|
16
|
+
next unless header.content?
|
17
|
+
header.unique_id = generate_unique_id(header.text)
|
18
|
+
if header.level - previous_level > 0
|
19
|
+
(previous_level + 1).upto(header.level) do |level|
|
20
|
+
ul_list[level - 1] << ul_list[level]
|
35
21
|
end
|
36
|
-
items << list_item(link_to(unique_id, text))
|
37
|
-
header_node["id"] = unique_id
|
38
22
|
end
|
39
|
-
|
23
|
+
ul_list[header.level] << ListItem.new(header: header)
|
24
|
+
previous_level = header.level
|
40
25
|
end
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
toc_html =
|
26
|
+
|
27
|
+
unless ul_list[1].items.empty?
|
28
|
+
toc_header = context[:toc_header] || ""
|
29
|
+
toc_html = "#{toc_header}#{ul_list[1].to_html}"
|
45
30
|
end
|
46
31
|
node.parent.replace(toc_html)
|
47
32
|
end
|
48
33
|
|
49
34
|
private
|
50
35
|
|
51
|
-
def
|
52
|
-
|
36
|
+
def generate_unique_id(text)
|
37
|
+
@headers ||= Hash.new(0)
|
38
|
+
id = text.downcase
|
39
|
+
id.tr!(" ", "-")
|
40
|
+
id.gsub!(/\s/, "")
|
41
|
+
|
42
|
+
unique_id =
|
43
|
+
if @headers[id] > 0
|
44
|
+
"#{id}-#{@headers[id]}"
|
45
|
+
else
|
46
|
+
id
|
47
|
+
end
|
48
|
+
@headers[id] += 1
|
49
|
+
unique_id
|
50
|
+
end
|
51
|
+
|
52
|
+
class Header
|
53
|
+
attr_reader :level, :text, :unique_id
|
54
|
+
|
55
|
+
def initialize(node)
|
56
|
+
@node = node
|
57
|
+
@level = node.name.tr("h", "").to_i
|
58
|
+
@text = node.text
|
59
|
+
@unique_id = ""
|
60
|
+
end
|
61
|
+
|
62
|
+
def unique_id=(id)
|
63
|
+
@node["id"] = id
|
64
|
+
@unique_id = id
|
65
|
+
end
|
66
|
+
|
67
|
+
def content?
|
68
|
+
@node.children.first
|
69
|
+
end
|
70
|
+
|
71
|
+
def link
|
72
|
+
%Q(<a href="##{unique_id}">#{text}</a>)
|
73
|
+
end
|
74
|
+
|
75
|
+
def to_s
|
76
|
+
@node.to_s
|
77
|
+
end
|
53
78
|
end
|
54
79
|
|
55
|
-
|
56
|
-
|
80
|
+
class EmptyHeader
|
81
|
+
def link
|
82
|
+
""
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class UnorderedList
|
87
|
+
attr_reader :items, :level
|
88
|
+
|
89
|
+
def initialize(html_class: nil, level: 1)
|
90
|
+
@html_class = html_class
|
91
|
+
@level = level
|
92
|
+
@items = []
|
93
|
+
end
|
94
|
+
|
95
|
+
def <<(item)
|
96
|
+
case
|
97
|
+
when item.is_a?(UnorderedList) && @items.last.is_a?(ListItem)
|
98
|
+
@items.last << item
|
99
|
+
when item.is_a?(UnorderedList) && @items.last.nil?
|
100
|
+
li = ListItem.new
|
101
|
+
li << item
|
102
|
+
@items << li
|
103
|
+
else
|
104
|
+
@items << item
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def to_html
|
109
|
+
if @html_class
|
110
|
+
%Q(<ul class="#{@html_class}">\n#{@items.map(&:to_html).join("\n")}\n</ul>)
|
111
|
+
else
|
112
|
+
%Q(<ul>\n#{@items.map(&:to_html).join("\n")}\n</ul>)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class ListItem
|
118
|
+
attr_reader :items
|
119
|
+
|
120
|
+
def initialize(header: EmptyHeader.new)
|
121
|
+
@header = header
|
122
|
+
@items = []
|
123
|
+
end
|
124
|
+
|
125
|
+
def <<(item)
|
126
|
+
@items << item
|
127
|
+
end
|
128
|
+
|
129
|
+
def to_html
|
130
|
+
if @items.empty?
|
131
|
+
%Q(<li>#{@header.link}</li>)
|
132
|
+
else
|
133
|
+
%Q(<li>#{@header.link}\n#{@items.map(&:to_html).join("\n")}\n</li>)
|
134
|
+
end
|
135
|
+
end
|
57
136
|
end
|
58
137
|
end
|
59
138
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: daimon_markdown
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- daimon developers
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: html-pipeline
|
@@ -185,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
185
185
|
version: '0'
|
186
186
|
requirements: []
|
187
187
|
rubyforge_project:
|
188
|
-
rubygems_version: 2.6.
|
188
|
+
rubygems_version: 2.6.8
|
189
189
|
signing_key:
|
190
190
|
specification_version: 4
|
191
191
|
summary: Markdown renderer for Daimon
|