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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7dc6824cc4df9719aba51eed6b8fe849b3885d07
4
- data.tar.gz: 8f4b326bf02fefc3d026c11f5a92a5b21c93c3f1
3
+ metadata.gz: 1b919648b289fa4707eb5d83c1543de90eb49add
4
+ data.tar.gz: 15f05ea47e81dfd6ec438426dc7290cabae176e4
5
5
  SHA512:
6
- metadata.gz: dfe1d12e0cac4f1c3ac054acb020665e7508d439475a4f81d37f9cb8ccffac3a6dc24186b7a6f9873b657effd55021ab314bac89381733e4ed501b87cf10aa5a
7
- data.tar.gz: 082116ac11b8cf37ded52adaee2c5f9532c7d3625f32cfc7971f48c2767823df826c63e0fd0f026e634c8fc8ef859fc81491ab74820112433bad61d4cd1ec805
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
- TODO: Write usage instructions here
25
+ For example, in your Rails application:
26
26
 
27
27
  ```ruby
28
- processor = DaimonMarkdown::Processor.new
29
- result = processor.call(input)
30
- puts result[:output].to_s
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?
@@ -6,6 +6,9 @@ module DaimonMarkdown
6
6
  class UnknownPluginError < StandardError
7
7
  end
8
8
 
9
+ class Error < StandardError
10
+ end
11
+
9
12
  class << self
10
13
  def lookup(name)
11
14
  PLUGIN_REGISTRY.fetch(name)
@@ -5,55 +5,134 @@ module DaimonMarkdown
5
5
 
6
6
  def call(limit = nil)
7
7
  toc_html = ""
8
- items = []
8
+ toc_class = context[:toc_class] || "section-nav"
9
9
 
10
- headers = Hash.new(0)
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
- level = header_node.name.tr("h", "").to_i
14
- next if limit && limit < level
15
- text = header_node.text
16
- id = text.downcase
17
- id.gsub!(/ /, "-")
18
- id.gsub!(/\s/, "")
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
- previous_level = level
23
+ ul_list[header.level] << ListItem.new(header: header)
24
+ previous_level = header.level
40
25
  end
41
- toc_class = context[:toc_class] || "section-nav"
42
- toc_header = context[:toc_header] || ""
43
- unless items.empty?
44
- toc_html = %Q(#{toc_header}<ul class="#{toc_class}">\n#{items.join("\n")}\n</ul>)
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 link_to(href, text)
52
- %Q(<a href="##{href}">#{text}</a>)
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
- def list_item(content)
56
- %Q(<li>#{content}</li>)
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
@@ -1,3 +1,3 @@
1
1
  module DaimonMarkdown
2
- VERSION = "0.6.0"
2
+ VERSION = "0.7.0"
3
3
  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.6.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: 2016-10-18 00:00:00.000000000 Z
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.4
188
+ rubygems_version: 2.6.8
189
189
  signing_key:
190
190
  specification_version: 4
191
191
  summary: Markdown renderer for Daimon