slacken 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5fc0f32867586c7b5d1bcc0f8d6f50a7397c8fc7
4
- data.tar.gz: 437c297ac0aec496d3002bc88770fce4919a5ec7
3
+ metadata.gz: 25a6903ad8c0859f0fd8140f05528957baf272aa
4
+ data.tar.gz: e251a3b49123a5fc4b04d20e07067bdacca79feb
5
5
  SHA512:
6
- metadata.gz: 4e4283f2ff319d82403f1465b2e8fe74da8a7f2e6d61e3489bfd44224038e7e719e8cba5165a88b8fd3902ed4113810b0baf51e392450fec8d7fca1554251a47
7
- data.tar.gz: 6ee2318990b5e0a67579a8114f5e9f1a5b8215b21b5f6110c717c3b154db4b5ae08a962628b057a97124eaa043ce9d5f0ce6f2cda80fd715b8c7b9c2311fecc0
6
+ metadata.gz: f603ab28cf2342146a68b18c0b154a8d776036494ff4cbb687ea52fce82745f8eb1091acb1bdb933f73be31d785ca4d30a5c855d5ff285a1ec77a1e50b41457e
7
+ data.tar.gz: 188a11057e56f4afb82720fb281e14948449da79a86ae948eb00a1faf7641126505274ab6595e516baa5c80a8b5a47f1aa776ea58919b37f6e97436ce0ac2135
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015 Tomoya Chiba
1
+ Copyright (c) 2015 Increments inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/lib/slacken.rb CHANGED
@@ -9,13 +9,22 @@ module Slacken
9
9
  require 'slacken/version'
10
10
 
11
11
  class << self
12
+ # Public: Translate HTML string into Markdown string.
13
+ #
14
+ # html_source - A String or IO.
15
+ #
16
+ # Returns a markdown String.
12
17
  def translate(html_source)
13
- convert(html_source).to_s
18
+ convert_html_to_document_component(html_source).to_element.to_s
14
19
  end
15
20
 
16
- def convert(html_source)
17
- Slacken::DomContainer.parse_html(html_source)
18
- .to_component.to_element
21
+ private
22
+
23
+ # Internal: Parse a HTML string and convert it to a DocumentComponent object.
24
+ #
25
+ # Returns a DocumentComponent.
26
+ def convert_html_to_document_component(html_source)
27
+ DocumentComponent.build_by_html(html_source)
19
28
  end
20
29
  end
21
30
  end
@@ -6,7 +6,7 @@ module Slacken
6
6
  # representing structure of a markup text.
7
7
  # A DocumentComponent has tree structure and has child nodes as `children`.
8
8
  class DocumentComponent
9
- NormalizeFilters = [
9
+ NORMALIZE_FILTERS = [
10
10
  Filters::StringfyEmoji,
11
11
  Filters::StringfyCheckbox,
12
12
  Filters::ExtractImgAlt,
@@ -26,6 +26,15 @@ module Slacken
26
26
 
27
27
  attr_reader :type, :attrs, :children, :marks
28
28
 
29
+ # Public: Parse a html source with nokogiri and create a component.
30
+ #
31
+ # html_source - A String or IO.
32
+ #
33
+ # Returns a DocumentComponent or nil.
34
+ def self.build_by_html(html_source)
35
+ DomContainer.new(Nokogiri::HTML(html_source)).to_component
36
+ end
37
+
29
38
  def initialize(type, children = [], attrs = {})
30
39
  @type = NodeType.create(type)
31
40
  @attrs = attrs
@@ -35,7 +44,10 @@ module Slacken
35
44
 
36
45
  def derive(new_children, updates = {})
37
46
  self.class.new(
38
- updates[:type] || type, new_children, updates[:attrs] || attrs)
47
+ updates[:type] || type,
48
+ new_children,
49
+ updates[:attrs] || attrs
50
+ )
39
51
  end
40
52
 
41
53
  # Public: Normalize this object's structure and convert it to MarkupElement.
@@ -44,7 +56,7 @@ module Slacken
44
56
  end
45
57
 
46
58
  def normalize
47
- NormalizeFilters.reduce(self) do |component, filter_klass|
59
+ NORMALIZE_FILTERS.reduce(self) do |component, filter_klass|
48
60
  filter_klass.new.call(component)
49
61
  end
50
62
  end
@@ -3,28 +3,41 @@ require 'nokogiri'
3
3
  module Slacken
4
4
  # Public: a DOM tree container parsed by Nokogiri.
5
5
  class DomContainer
6
- attr_reader :root
7
-
8
- # Public: Parse a html source with nokogiri and create a container.
9
- def self.parse_html(body)
10
- new(Nokogiri::HTML(body))
11
- end
12
-
13
6
  def initialize(root)
14
7
  @root = root
15
8
  end
16
9
 
17
- def to_component(node = root)
18
- children = node.children.map { |nd| to_component(nd) }.compact
19
- leave(node, children)
10
+ # Public: Create a DocumentComponent of the root node.
11
+ #
12
+ # Returns a DocumentComponent or nil.
13
+ def to_component
14
+ build_document_component(@root)
20
15
  end
21
16
 
22
17
  private
23
18
 
24
- def leave(node, children)
25
- if !(node.respond_to?(:html_dtd?) && node.html_dtd?)
26
- DocumentComponent.new(node.name.downcase, children, attrs_of(node))
27
- end
19
+ # Internal: Build a DocumentComponent of the given node recursively.
20
+ #
21
+ # current_node - A Nokogiri::HTML::Document.
22
+ #
23
+ # Returns a DocumentComponent.
24
+ def build_document_component(node)
25
+ DocumentComponent.new(
26
+ node.name.downcase,
27
+ build_document_components_array(node.children),
28
+ attrs_of(node)
29
+ )
30
+ end
31
+
32
+ # Internal: Build sequence of DocumentComponent objects for each given nodes.
33
+ #
34
+ # nodes - A Nokogiri::XML::NodeSet.
35
+ #
36
+ # Returns an Array of DocumentComponents.
37
+ def build_document_components_array(node_set)
38
+ node_set
39
+ .reject { |node| node.respond_to?(:html_dtd?) && node.html_dtd? }
40
+ .map { |node| build_document_component(node) }
28
41
  end
29
42
 
30
43
  def attrs_of(node)
@@ -28,7 +28,7 @@ module Slacken::Filters
28
28
 
29
29
  component.marks[:blank] =
30
30
  case component.type.name
31
- when :pre, :ul, :li, :br, :hr, :img, :checkbox
31
+ when :pre, :ul, :li, :br, :hr, :img, :checkbox, :td
32
32
  false
33
33
  when :text, :emoji
34
34
  content = component.attrs[:content]
@@ -23,16 +23,16 @@ module Slacken::Filters
23
23
 
24
24
  def sanitize_list(component)
25
25
  if component.type.member_of?(:li, :dd)
26
- head, *tails = component.children
27
- component.derive(
28
- [sanitize_list_item(head), *tails.map(&method(:sanitize_list))]
29
- )
26
+ head, *tails = component.children
27
+ component.derive(
28
+ [sanitize_list_item(head), *tails.map(&method(:sanitize_list))]
29
+ )
30
30
  elsif component.type.allowed_in_list?
31
31
  component.derive(component.children.map(&method(:sanitize_list)))
32
32
  else
33
33
  component.derive(
34
34
  component.children.map(&method(:sanitize_list)),
35
- type: block? ? :div : :span
35
+ type: component.block? ? :div : :span
36
36
  )
37
37
  end
38
38
  end
@@ -1,3 +1,3 @@
1
1
  module Slacken
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
data/slacken.gemspec CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
8
8
  gem.summary = %q{Translate HTML sources to markup texts for slack}
9
9
  gem.description = %q{Translate HTML sources to markup texts for slack}
10
10
  gem.license = "MIT"
11
- gem.authors = ["Tomoya Chiba"]
12
- gem.email = "tomo.asleep@gmail.com"
11
+ gem.authors = ["Tomoya Chiba", "Yuku Takahashi"]
12
+ gem.email = ["tomo.asleep@qiita.com", "yuku@qiita.com"]
13
13
  gem.homepage = "https://rubygems.org/gems/slacken"
14
14
 
15
15
  gem.files = `git ls-files`.split($/)
@@ -22,6 +22,7 @@ Gem::Specification.new do |gem|
22
22
  gem.add_development_dependency 'rdoc', '~> 3.0'
23
23
  gem.add_development_dependency 'rspec', '~> 3.0'
24
24
  gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
25
+ gem.add_development_dependency 'unindent', '~> 1.0'
25
26
 
26
27
  gem.add_runtime_dependency 'nokogiri', '~> 1.6'
27
28
  gem.add_runtime_dependency 'kosi', '~> 1.0'
@@ -1,11 +1,15 @@
1
- # Public: Provide DSL methods to build a DocumentComponent like S-exp.
2
- module DocumentComponentDsl
3
- def c(type_name, *children)
4
- options = children.first.is_a?(Hash) ? children.shift : {}
5
- Slacken::DocumentComponent.new(type_name, children, options)
6
- end
1
+ module Slacken
2
+ module Helpers
3
+ # Public: Provide DSL methods to build a DocumentComponent like S-exp.
4
+ module DocumentComponentDsl
5
+ def c(type_name, *children)
6
+ options = children.first.is_a?(Hash) ? children.shift : {}
7
+ Slacken::DocumentComponent.new(type_name, children, options)
8
+ end
7
9
 
8
- def text(content)
9
- Slacken::DocumentComponent.new(:text, [], content: content)
10
+ def text(content)
11
+ Slacken::DocumentComponent.new(:text, [], content: content)
12
+ end
13
+ end
10
14
  end
11
15
  end
@@ -1,16 +1,18 @@
1
1
  require 'spec_helper'
2
2
 
3
- module Slacken
4
- describe DocumentComponent do
5
- describe '#normalize' do
6
- subject { DomContainer.parse_html(source).to_component.normalize }
7
- let(:source) { fixture('example.html') }
3
+ describe Slacken::DocumentComponent do
4
+ let(:document_component) { described_class.build_by_html(source) }
5
+ # If you change the behavior, you should run `scripts/update_markup_fixture.rb`
6
+ # to update fixture file.
7
+ let(:source) { fixture('example.html') }
8
8
 
9
- DocumentComponent::NormalizeFilters.each do |klass|
10
- context "when #{klass.name} checks the result's validity" do
11
- let(:filter) { klass.new }
12
- it { is_expected.to satisfy(&filter.method(:valid?)) }
13
- end
9
+ describe '#normalize' do
10
+ subject { document_component.normalize }
11
+
12
+ Slacken::DocumentComponent::NORMALIZE_FILTERS.each do |klass|
13
+ context "when #{klass.name} checks the result's validity" do
14
+ let(:filter) { klass.new }
15
+ it { is_expected.to satisfy(&filter.method(:valid?)) }
14
16
  end
15
17
  end
16
18
  end
@@ -33,4 +33,18 @@ describe Slacken::Filters::SanitizeList, dsl: true do
33
33
  it { is_expected.to be_truthy }
34
34
  end
35
35
  end
36
+
37
+ describe '#call' do
38
+ let(:filter) { described_class.new.call(component) }
39
+
40
+ context 'when a list has a img tag' do
41
+ let(:component) do
42
+ c(:ul, c(:img))
43
+ end
44
+
45
+ it 'changes img to div tag' do
46
+ expect(filter.children.first.type.name).to eq :div
47
+ end
48
+ end
49
+ end
36
50
  end
data/spec/slacken_spec.rb CHANGED
@@ -3,13 +3,326 @@ require 'spec_helper'
3
3
  describe Slacken do
4
4
  describe '#translate' do
5
5
  subject { described_class.translate(source) }
6
- let(:source) { fixture('example.html') }
7
6
 
8
- # This test checks whether the behavior of this translation engine is unexpectedly broken.
9
- # If you change the behavior, you should run `scripts/update_markup_fixture.rb`
10
- # to update fixture file.
11
- it 'translates as expected' do
12
- expect(subject).to eq(fixture('markup_text.txt'))
7
+ context 'when h1 is given' do
8
+ let(:source) do
9
+ <<-EOS.unindent
10
+ <h1>
11
+ <span id="heading-bold"></span>
12
+ <a><i class="fa fa-link"></i></a>
13
+ heading <em>italic</em> <strong>bold</strong>
14
+ </h1>
15
+ EOS
16
+ end
17
+
18
+ it 'wraps inner text with "*"' do
19
+ should eq '*heading _italic_ bold*'
20
+ end
21
+ end
22
+
23
+ context 'when p is given' do
24
+ let(:source) { '<p>hello world</p>' }
25
+
26
+ it 'returns inner text' do
27
+ should eq "hello world"
28
+ end
29
+ end
30
+
31
+ context 'when br is given' do
32
+ let(:source) { '<p>hello<br>world</p>' }
33
+
34
+ it 'converts br into new line char' do
35
+ should eq "hello\nworld"
36
+ end
37
+ end
38
+
39
+ context 'when em is given' do
40
+ let(:source) { '<p><em>italic</em></p>' }
41
+
42
+ it 'wraps inner text with "_"' do
43
+ should eq '_italic_'
44
+ end
45
+ end
46
+
47
+ context 'when string is given' do
48
+ let(:source) { '<p><strong>bold</strong></p>' }
49
+
50
+ it 'wraps inner text with "*"' do
51
+ should eq '*bold*'
52
+ end
53
+ end
54
+
55
+ context 'when code is given' do
56
+ let(:source) { '<p><code>code</code></p>' }
57
+
58
+ it 'wraps inner text with "`"' do
59
+ should eq '`code`'
60
+ end
61
+ end
62
+
63
+ context 'when emoji img is given' do
64
+ let(:source) do
65
+ <<-EOS.unindent
66
+ <p>
67
+ hello
68
+ <img class="emoji" title=":eyes:" alt=":eyes:" src="https://cdn.qiita.com/emoji/unicode/1f440.png" height="20" width="20" align="absmiddle">
69
+ world
70
+ <img class="emoji" title=":bowtie:" alt=":bowtie:" src="https://cdn.qiita.com/emoji/bowtie.png" height="20" width="20" align="absmiddle">
71
+ </p>
72
+ EOS
73
+ end
74
+
75
+ it 'replaces img elements with corresponding emoji notation' do
76
+ should eq 'hello :eyes: world :bowtie:'
77
+ end
78
+ end
79
+
80
+ context 'when nested ul, ol and li elements are given' do
81
+ let(:source) do
82
+ <<-EOS.unindent
83
+ <ol>
84
+ <li>リスト1
85
+ <ul>
86
+ <li>リスト1-1</li>
87
+ <li>リスト1-2</li>
88
+ </ul>
89
+ </li>
90
+ <li>リスト2
91
+ <ol>
92
+ <li>リスト2-1</li>
93
+ </ol>
94
+ </li>
95
+ </ol>
96
+ EOS
97
+ end
98
+
99
+ it 'converts to list notation' do
100
+ should eq <<-EOS.unindent.chomp
101
+ 1. リスト1
102
+ • リスト1-1
103
+ • リスト1-2
104
+ 2. リスト2
105
+ 1. リスト2-1
106
+ EOS
107
+ end
108
+ end
109
+
110
+ context 'when task lists are given' do
111
+ let(:source) do
112
+ <<-EOS.unindent
113
+ <ul>
114
+ <li class="task-list-item">
115
+ <input type="checkbox" class="task-list-item-checkbox" checked disabled>Checked item</li>
116
+ <li class="task-list-item">
117
+ <input type="checkbox" class="task-list-item-checkbox" disabled>Unchecked item</li>
118
+ </ul>
119
+ EOS
120
+ end
121
+
122
+ it 'converts to list notation with ascii checkbox' do
123
+ should eq <<-EOS.unindent.chomp
124
+ • [x] Checked item
125
+ • [ ] Unchecked item
126
+ EOS
127
+ end
128
+ end
129
+
130
+ context 'when dl is given' do
131
+ let(:source) do
132
+ <<-EOS.unindent
133
+ <dl>
134
+ <dt>定義語リストとは?</dt>
135
+ <dd>こんなかんじで単語の意味を説明していくリストです。</dd>
136
+ <dt>他の単語</dt>
137
+ <dd>ここに説明を書く</dd>
138
+ </dl>
139
+ EOS
140
+ end
141
+
142
+ it 'converts to list notation' do
143
+ should eq <<-EOS.unindent.chomp
144
+ • 定義語リストとは?
145
+ • こんなかんじで単語の意味を説明していくリストです。
146
+ • 他の単語
147
+ • ここに説明を書く
148
+ EOS
149
+ end
150
+ end
151
+
152
+ context 'when blockquote is given' do
153
+ let(:source) do
154
+ <<-EOS.unindent
155
+ <blockquote>
156
+ <p>この文字列は引用されたものです<br>
157
+ インデントされているはず<br>
158
+ これはもインデントされている</p>
159
+ </blockquote>
160
+
161
+ <p>これはインデントされない</p>
162
+ EOS
163
+ end
164
+
165
+ it 'inserts ">" to each lines' do
166
+ should eq <<-EOS.unindent.chomp
167
+ > この文字列は引用されたものです
168
+ > インデントされているはず
169
+ > これはもインデントされている
170
+
171
+ これはインデントされない
172
+ EOS
173
+ end
174
+ end
175
+
176
+ context 'when code block is given' do
177
+ let(:source) do
178
+ <<-EOS.unindent
179
+ <div class="code-frame" data-lang="rb"><div class="highlight"><pre><span class="k">class</span> <span class="nc">Klass</span>
180
+ <span class="k">def</span> <span class="nf">method</span>
181
+ <span class="nb">puts</span> <span class="s1">'method called!'</span>
182
+ <span class="k">end</span>
183
+ <span class="k">end</span>
184
+ </pre></div></div>
185
+ EOS
186
+ end
187
+
188
+ it 'wraps inner text with "```"' do
189
+ should eq <<-EOS.unindent.chomp
190
+ ```class Klass
191
+ def method
192
+ puts 'method called!'
193
+ end
194
+ end
195
+ ```
196
+ EOS
197
+ end
198
+ end
199
+
200
+ context 'when table is given' do
201
+ let(:source) do
202
+ <<-EOS.unindent
203
+ <table>
204
+ <thead>
205
+ <tr>
206
+ <th>Header1</th>
207
+ <th>Header2</th>
208
+ </tr>
209
+ </thead>
210
+ <tbody>
211
+ <tr>
212
+ <td>Cell1</td>
213
+ <td>Cell2</td>
214
+ </tr>
215
+ <tr>
216
+ <td>hello</td>
217
+ <td>world</td>
218
+ </tr>
219
+ </tbody>
220
+ </table>
221
+ EOS
222
+ end
223
+
224
+ it 'converts html to table notation' do
225
+ should eq <<-EOS.unindent.chomp
226
+ +-------+-------+
227
+ |Header1|Header2|
228
+ +-------+-------+
229
+ |Cell1 |Cell2 |
230
+ |hello |world |
231
+ +-------+-------+
232
+ EOS
233
+ end
234
+ end
235
+
236
+ context 'when table with empty td is given' do
237
+ let(:source) do
238
+ <<-EOS.unindent
239
+ <table>
240
+ <thead>
241
+ <tr>
242
+ <th>Header1</th>
243
+ <th>Header2</th>
244
+ </tr>
245
+ </thead>
246
+ <tbody>
247
+ <tr>
248
+ <td>A</td>
249
+ <td></td>
250
+ </tr>
251
+ <tr>
252
+ <td>B</td>
253
+ <td>C</td>
254
+ </tr>
255
+ </tbody>
256
+ </table>
257
+ EOS
258
+ end
259
+
260
+ it 'converts html to table notation' do
261
+ should eq <<-EOS.unindent.chomp
262
+ +-------+-------+
263
+ |Header1|Header2|
264
+ +-------+-------+
265
+ |A | |
266
+ |B |C |
267
+ +-------+-------+
268
+ EOS
269
+ end
270
+ end
271
+
272
+ context 'when img is given' do
273
+ let(:source) { "<p><img src='#{src}' alt='#{alt}'></p>" }
274
+ let(:src) { 'http://cdn.qiita.com/logo.png' }
275
+ let(:alt) { 'Qiita logo' }
276
+
277
+ it 'convert inner text to img notation' do
278
+ should eq "<#{src}|#{alt}>"
279
+ end
280
+ end
281
+
282
+ context 'when img in a is given' do
283
+ let(:source) { "<p><a href='#{src}'><img src='#{src}' alt='#{alt}'></a></p>" }
284
+ let(:src) { 'http://cdn.qiita.com/logo.png' }
285
+ let(:alt) { 'Qiita logo' }
286
+
287
+ it 'ignores the link' do
288
+ should eq "<#{src}|#{alt}>"
289
+ end
290
+ end
291
+
292
+ context 'when a is given' do
293
+ let(:source) { '<p><a href="http://qiita.com">qiita</a></p>' }
294
+
295
+ it 'converts to link notation' do
296
+ should eq "<http://qiita.com|qiita>"
297
+ end
298
+ end
299
+
300
+ context 'when hr is given' do
301
+ let(:source) do
302
+ <<-EOS.unindent
303
+ <p>before</p>
304
+ <hr>
305
+ <p>after</p>
306
+ EOS
307
+ end
308
+
309
+ it 'converts to "-----------"' do
310
+ should eq <<-EOS.unindent.chomp
311
+ before
312
+
313
+ -----------
314
+
315
+ after
316
+ EOS
317
+ end
318
+ end
319
+
320
+ context 'when del is given' do
321
+ let(:source) { '<del>ignore</del>' }
322
+
323
+ it 'returns inner text' do
324
+ should eq 'ignore'
325
+ end
13
326
  end
14
327
  end
15
328
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'rspec'
2
2
  require 'slacken'
3
+ require 'unindent'
3
4
 
4
5
  require 'helpers/document_component_dsl'
5
6
 
@@ -8,5 +9,5 @@ def fixture(name)
8
9
  end
9
10
 
10
11
  RSpec.configure do |c|
11
- c.include DocumentComponentDsl, dsl: true
12
+ c.include Slacken::Helpers::DocumentComponentDsl, dsl: true
12
13
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slacken
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomoya Chiba
8
+ - Yuku Takahashi
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2015-08-10 00:00:00.000000000 Z
12
+ date: 2015-08-17 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
@@ -80,6 +81,20 @@ dependencies:
80
81
  - - "~>"
81
82
  - !ruby/object:Gem::Version
82
83
  version: '0.2'
84
+ - !ruby/object:Gem::Dependency
85
+ name: unindent
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '1.0'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '1.0'
83
98
  - !ruby/object:Gem::Dependency
84
99
  name: nokogiri
85
100
  requirement: !ruby/object:Gem::Requirement
@@ -109,7 +124,9 @@ dependencies:
109
124
  - !ruby/object:Gem::Version
110
125
  version: '1.0'
111
126
  description: Translate HTML sources to markup texts for slack
112
- email: tomo.asleep@gmail.com
127
+ email:
128
+ - tomo.asleep@qiita.com
129
+ - yuku@qiita.com
113
130
  executables: []
114
131
  extensions: []
115
132
  extra_rdoc_files: []
@@ -183,7 +200,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
200
  version: '0'
184
201
  requirements: []
185
202
  rubyforge_project:
186
- rubygems_version: 2.4.5
203
+ rubygems_version: 2.2.2
187
204
  signing_key:
188
205
  specification_version: 4
189
206
  summary: Translate HTML sources to markup texts for slack