slacken 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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