slacken 0.1.0 → 0.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -0
  3. data/README.md +5 -3
  4. data/{sample → examples}/out.txt +0 -0
  5. data/{sample → examples}/source.html +0 -0
  6. data/lib/slacken/document_component.rb +23 -36
  7. data/lib/slacken/dom_container.rb +1 -1
  8. data/lib/slacken/filter.rb +27 -0
  9. data/lib/slacken/filters.rb +19 -0
  10. data/lib/slacken/filters/elim_blanks.rb +41 -0
  11. data/lib/slacken/filters/elim_invalid_links.rb +33 -0
  12. data/lib/slacken/filters/elim_line_breaks.rb +36 -0
  13. data/lib/slacken/filters/extract_img_alt.rb +18 -0
  14. data/lib/slacken/filters/group_indent.rb +28 -0
  15. data/lib/slacken/filters/group_inlines.rb +31 -0
  16. data/lib/slacken/filters/sanitize_headline.rb +46 -0
  17. data/lib/slacken/filters/sanitize_link.rb +48 -0
  18. data/lib/slacken/filters/sanitize_list.rb +57 -0
  19. data/lib/slacken/filters/sanitize_table.rb +44 -0
  20. data/lib/slacken/filters/stringfy_checkbox.rb +26 -0
  21. data/lib/slacken/filters/stringfy_emoji.rb +26 -0
  22. data/lib/slacken/node_type.rb +2 -1
  23. data/lib/slacken/render_element.rb +2 -0
  24. data/lib/slacken/rendering.rb +0 -1
  25. data/lib/slacken/version.rb +1 -1
  26. data/scripts/update_markup_fixture.rb +3 -3
  27. data/spec/slacken/document_component_spec.rb +6 -8
  28. data/spec/slacken/filters/elim_blanks_spec.rb +32 -0
  29. data/spec/slacken/filters/elim_invalid_links_spec.rb +47 -0
  30. data/spec/slacken/filters/elim_line_breaks_spec.rb +39 -0
  31. data/spec/slacken/filters/group_indent_spec.rb +35 -0
  32. data/spec/slacken/filters/group_inlines_spec.rb +31 -0
  33. data/spec/slacken/filters/sanitize_headline_spec.rb +29 -0
  34. data/spec/slacken/filters/sanitize_link_spec.rb +23 -0
  35. data/spec/slacken/filters/sanitize_list_spec.rb +36 -0
  36. data/spec/slacken/filters/sanitize_table_spec.rb +39 -0
  37. data/spec/slacken_spec.rb +3 -0
  38. data/spec/spec_helper.rb +1 -2
  39. metadata +37 -26
  40. data/lib/slacken/document_component/elim_blanks.rb +0 -36
  41. data/lib/slacken/document_component/elim_invalid_links.rb +0 -26
  42. data/lib/slacken/document_component/elim_line_breaks.rb +0 -27
  43. data/lib/slacken/document_component/extract_img_alt.rb +0 -12
  44. data/lib/slacken/document_component/group_indent.rb +0 -27
  45. data/lib/slacken/document_component/group_inlines.rb +0 -26
  46. data/lib/slacken/document_component/sanitize_link_containers.rb +0 -40
  47. data/lib/slacken/document_component/sanitize_special_tag_containers.rb +0 -102
  48. data/lib/slacken/document_component/stringfy_checkbox.rb +0 -20
  49. data/lib/slacken/document_component/stringfy_emoji.rb +0 -20
  50. data/spec/slacken/document_component/elim_blanks_spec.rb +0 -34
  51. data/spec/slacken/document_component/elim_invalid_links_spec.rb +0 -49
  52. data/spec/slacken/document_component/elim_line_breaks_spec.rb +0 -41
  53. data/spec/slacken/document_component/group_indent_spec.rb +0 -37
  54. data/spec/slacken/document_component/group_inlines_spec.rb +0 -33
  55. data/spec/slacken/document_component/sanitize_special_tag_containers_spec.rb +0 -64
@@ -0,0 +1,57 @@
1
+ module Slacken::Filters
2
+ # Public: Sanitize not allowed tags in list.
3
+ class SanitizeList < Slacken::Filter
4
+ def call(component)
5
+ case component.type.name
6
+ when :ul, :ol, :dl
7
+ component.derive(component.children.map(&method(:sanitize_list)))
8
+ else
9
+ component.derive(component.children.map(&method(:call)))
10
+ end
11
+ end
12
+
13
+ def valid?(component)
14
+ case component.type.name
15
+ when :ul, :ol, :dl
16
+ component.children.all?(&method(:list_sanitized?))
17
+ else
18
+ component.children.all?(&method(:valid?))
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def sanitize_list(component)
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
+ )
30
+ elsif component.type.allowed_in_list?
31
+ component.derive(component.children.map(&method(:sanitize_list)))
32
+ else
33
+ component.derive(
34
+ component.children.map(&method(:sanitize_list)),
35
+ type: block? ? :div : :span
36
+ )
37
+ end
38
+ end
39
+
40
+ def sanitize_list_item(component)
41
+ if component.type.allowed_as_list_item?
42
+ component.derive(component.children.map(&method(:sanitize_list_item)))
43
+ else
44
+ # No block tags are allowed.
45
+ component.derive(component.children.map(&method(:sanitize_list_item)), type: :span)
46
+ end
47
+ end
48
+
49
+ def list_sanitized?(component)
50
+ if component.type.allowed_in_list?
51
+ component.children.all?(&method(:list_sanitized?))
52
+ else
53
+ false
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,44 @@
1
+ module Slacken::Filters
2
+ # Public: Sanitize not allowed tags in table.
3
+ class SanitizeTable < Slacken::Filter
4
+ def call(component)
5
+ if component.type.member_of?(:table)
6
+ component.derive(component.children.map(&method(:sanitize_table)))
7
+ else
8
+ component.derive(component.children.map(&method(:call)))
9
+ end
10
+ end
11
+
12
+ def valid?(component)
13
+ if component.type.member_of?(:table)
14
+ component.children.all?(&method(:table_sanitized?))
15
+ else
16
+ component.children.all?(&method(:valid?))
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def sanitize_table(component)
23
+ if component.type.allowed_in_table?
24
+ component.derive(
25
+ component.children.map(&method(:sanitize_table))
26
+ )
27
+ else
28
+ # No block tags are allowed.
29
+ component.derive(
30
+ component.children.map(&method(:sanitize_table)),
31
+ type: :span
32
+ )
33
+ end
34
+ end
35
+
36
+ def table_sanitized?(component)
37
+ if component.type.allowed_in_table?
38
+ component.children.all?(&method(:table_sanitized?))
39
+ else
40
+ false
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,26 @@
1
+ module Slacken::Filters
2
+ # Public: Change checkbox input node to checkbox node.
3
+ class StringfyCheckbox < Slacken::Filter
4
+ def call(component)
5
+ if checkbox_input?(component)
6
+ component.class.new(:checkbox, [], checked: component.attrs[:checked])
7
+ else
8
+ component.derive(component.children.map(&method(:call)))
9
+ end
10
+ end
11
+
12
+ def valid?(component)
13
+ if checkbox_input?(component)
14
+ false
15
+ else
16
+ component.children.all?(&method(:valid?))
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def checkbox_input?(component)
23
+ component.type.member_of?(:input) && component.attrs[:type] == 'checkbox'
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Slacken::Filters
2
+ # Public: Convert emoji image nodes to emoji nodes.
3
+ class StringfyEmoji < Slacken::Filter
4
+ def call(component)
5
+ if emoji_img_tag?(component)
6
+ component.class.new(:emoji, [], content: component.attrs[:alt])
7
+ else
8
+ component.derive(component.children.map(&method(:call)))
9
+ end
10
+ end
11
+
12
+ def valid?(component)
13
+ if emoji_img_tag?(component)
14
+ false
15
+ else
16
+ component.children.all?(&method(:valid?))
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def emoji_img_tag?(component)
23
+ component.type.member_of?(:img) && component.attrs[:class].include?('emoji')
24
+ end
25
+ end
26
+ end
@@ -1,4 +1,5 @@
1
1
  module Slacken
2
+ # Public: Representing type of DocumentComponent.
2
3
  class NodeType
3
4
  def self.create(name)
4
5
  name.is_a?(NodeType) ? name : new(name)
@@ -43,7 +44,7 @@ module Slacken
43
44
  end
44
45
 
45
46
  def allowed_in_table?
46
- member_of?(%i(code b strong i em wrapper span).concat(text_types))
47
+ member_of?(%i(code b strong i em wrapper span thead tbody tr th td).concat(text_types))
47
48
  end
48
49
 
49
50
  def allowed_in_link?
@@ -1,4 +1,6 @@
1
1
  module Slacken
2
+ # Internal: Representing a tree structure of a document and
3
+ # responsible for rendering the structure to string.
2
4
  class RenderElement
3
5
  attr_reader :type, :renderer, :attrs, :children
4
6
 
@@ -60,7 +60,6 @@ module Slacken
60
60
  end
61
61
 
62
62
  # Public: an intermediate object to stringfy RenderElements.
63
- #
64
63
  class RenderingGroup
65
64
  attr_reader :children
66
65
  def initialize(children)
@@ -1,3 +1,3 @@
1
1
  module Slacken
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -3,6 +3,6 @@ require 'slacken'
3
3
  fixture_dir = File.expand_path('../spec/fixtures', __dir__)
4
4
 
5
5
  File.write(
6
- File.expand_path('markup_text.txt', fixture_dir),
7
- Slacken.translate(File.read(File.expand_path('example.html', fixture_dir)))
8
- )
6
+ File.join(fixture_dir, 'markup_text.txt'),
7
+ Slacken.translate(File.read(File.join(fixture_dir, 'example.html')))
8
+ )
@@ -6,14 +6,12 @@ module Slacken
6
6
  subject { DomContainer.parse_html(source).to_component.normalize }
7
7
  let(:source) { fixture('example.html') }
8
8
 
9
- it { is_expected.to have_no_blanks }
10
- it { is_expected.to have_no_invalid_links }
11
- it { is_expected.to have_no_line_breaks }
12
- it { is_expected.to be_indent_grouped }
13
- it { is_expected.to be_inlines_grouped }
14
- it { is_expected.to be_sanitized }
15
- it { is_expected.to be_emoji_stringfied }
16
- it { is_expected.to be_checkbox_stringfied }
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
14
+ end
17
15
  end
18
16
  end
19
17
  end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slacken::Filters::ElimBlanks, dsl: true do
4
+ describe '#valid?' do
5
+ subject { described_class.new.valid?(component) }
6
+
7
+ context 'when a component obviously having no blanks is given' do
8
+ let(:component) do
9
+ c(:div, text('hello world!'))
10
+ end
11
+
12
+ it { is_expected.to be_truthy }
13
+ end
14
+
15
+ context 'when a component with blank component.derive is given' do
16
+ let(:component) do
17
+ c(:div, text(''), c(:div), c(:span))
18
+ end
19
+
20
+ it { is_expected.to be_falsey }
21
+ end
22
+
23
+ context 'when a component with a img is given' do
24
+ let(:component) do
25
+ c(:div, c(:img))
26
+ end
27
+
28
+ it { is_expected.to be_truthy }
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slacken::Filters::ElimInvalidLinks, dsl: true do
4
+ describe '#valid?' do
5
+ subject { described_class.new.valid?(component) }
6
+
7
+ context 'when a http link is given' do
8
+ let(:component) do
9
+ c(:a, { href: 'http://example.com' })
10
+ end
11
+
12
+ it { is_expected.to be_truthy }
13
+ end
14
+
15
+ context 'when a https link is given' do
16
+ let(:component) do
17
+ c(:a, { href: 'https://example.com' })
18
+ end
19
+
20
+ it { is_expected.to be_truthy }
21
+ end
22
+
23
+ context "when a disallowed link containing 'http://' is given" do
24
+ let(:component) do
25
+ c(:a, { href: '#hogefugahttp://' })
26
+ end
27
+
28
+ it { is_expected.to be_falsey }
29
+ end
30
+
31
+ context 'when a disallowed link is given' do
32
+ let(:component) do
33
+ c(:a, { href: '#hogehoge' })
34
+ end
35
+
36
+ it { is_expected.to be_falsey }
37
+ end
38
+
39
+ context 'when a disallowed link occurs as a component\'s component.derive' do
40
+ let(:component) do
41
+ c(:div, c(:span, c(:a, { href: '#hogehoge' })))
42
+ end
43
+
44
+ it { is_expected.to be_falsey }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slacken::Filters::ElimLineBreaks, dsl: true do
4
+ describe '#valid?' do
5
+ subject { described_class.new.valid?(component) }
6
+
7
+ context 'when no linebreaks occur' do
8
+ let(:component) do
9
+ c(:div, c(:h1, text('yo!')), c(:wrapper, text('hello world!'), text('another')))
10
+ end
11
+
12
+ it { is_expected.to be_truthy }
13
+ end
14
+
15
+ context 'when a linebreak occurs in a inline component' do
16
+ let(:component) do
17
+ c(:div, c(:h1, text('yo!')), c(:wrapper, text('hello world!'), text("another\n")))
18
+ end
19
+
20
+ it { is_expected.to be_falsey }
21
+ end
22
+
23
+ context 'when a linebreak occurs in a block component' do
24
+ let(:component) do
25
+ c(:div, c(:h1, text("yo\n!")), c(:wrapper, text('hello world!'), text("another")))
26
+ end
27
+
28
+ it { is_expected.to be_falsey }
29
+ end
30
+
31
+ context 'when a linebreak occurs in a pre tag' do
32
+ let(:component) do
33
+ c(:div, c(:pre, text("yo\n!")), c(:wrapper, text('hello world!'), text("another")))
34
+ end
35
+
36
+ it { is_expected.to be_truthy }
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slacken::Filters::GroupIndent, dsl: true do
4
+ describe '#valid?' do
5
+ subject { described_class.new.valid?(component) }
6
+
7
+ context 'when a indented list component is given' do
8
+ let(:component) do
9
+ c(:ul,
10
+ c(:li,
11
+ text('List Heading'),
12
+ c(:indent,
13
+ text('List Content1'),
14
+ c(:span, text('List Content2'), text('List Content3'))
15
+ )))
16
+ end
17
+
18
+ it { is_expected.to be_truthy }
19
+ end
20
+
21
+ context 'when a indented list where child component is not indented is given' do
22
+ let(:component) do
23
+ c(:ul,
24
+ c(:li,
25
+ text('List Heading'),
26
+ c(:span,
27
+ text('List Content1'),
28
+ c(:span, text('List Content2'), text('List Content3'))
29
+ )))
30
+ end
31
+
32
+ it { is_expected.to be_falsey }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slacken::Filters::GroupInlines, dsl: true do
4
+ describe '#valid?' do
5
+ subject { described_class.new.valid?(component) }
6
+
7
+ context 'when a grouped component is given' do
8
+ let(:component) do
9
+ c(:div, c(:wrapper, text('hello world!'), text('another')))
10
+ end
11
+
12
+ it { is_expected.to be_truthy }
13
+ end
14
+
15
+ context 'when a component whose inline components are exposed is given' do
16
+ let(:component) do
17
+ c(:div, text(''), c(:div), c(:span))
18
+ end
19
+
20
+ it { is_expected.to be_falsey }
21
+ end
22
+
23
+ context 'when a component with only block components is given' do
24
+ let(:component) do
25
+ c(:div, c(:div), c(:img), c(:p, c(:h1)))
26
+ end
27
+
28
+ it { is_expected.to be_truthy }
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Slacken::Filters::SanitizeHeadline, dsl: true do
4
+ describe '#valid?' do
5
+ subject { described_class.new.valid?(component) }
6
+
7
+ context 'when a code occurs in a header' do
8
+ let(:component) do
9
+ c(:h3,
10
+ text('A Ruby Code is Given: '),
11
+ c(:span,
12
+ c(:code, text("puts('hello, world!')"))))
13
+ end
14
+
15
+ it { is_expected.to be_falsey }
16
+ end
17
+
18
+ context 'when only allowed tags occur in a header' do
19
+ let(:component) do
20
+ c(:h3,
21
+ text('hoge'),
22
+ c(:i, text('fuga')),
23
+ c(:span, text('piyo')))
24
+ end
25
+
26
+ it { is_expected.to be_truthy }
27
+ end
28
+ end
29
+ end