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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/README.md +5 -3
- data/{sample → examples}/out.txt +0 -0
- data/{sample → examples}/source.html +0 -0
- data/lib/slacken/document_component.rb +23 -36
- data/lib/slacken/dom_container.rb +1 -1
- data/lib/slacken/filter.rb +27 -0
- data/lib/slacken/filters.rb +19 -0
- data/lib/slacken/filters/elim_blanks.rb +41 -0
- data/lib/slacken/filters/elim_invalid_links.rb +33 -0
- data/lib/slacken/filters/elim_line_breaks.rb +36 -0
- data/lib/slacken/filters/extract_img_alt.rb +18 -0
- data/lib/slacken/filters/group_indent.rb +28 -0
- data/lib/slacken/filters/group_inlines.rb +31 -0
- data/lib/slacken/filters/sanitize_headline.rb +46 -0
- data/lib/slacken/filters/sanitize_link.rb +48 -0
- data/lib/slacken/filters/sanitize_list.rb +57 -0
- data/lib/slacken/filters/sanitize_table.rb +44 -0
- data/lib/slacken/filters/stringfy_checkbox.rb +26 -0
- data/lib/slacken/filters/stringfy_emoji.rb +26 -0
- data/lib/slacken/node_type.rb +2 -1
- data/lib/slacken/render_element.rb +2 -0
- data/lib/slacken/rendering.rb +0 -1
- data/lib/slacken/version.rb +1 -1
- data/scripts/update_markup_fixture.rb +3 -3
- data/spec/slacken/document_component_spec.rb +6 -8
- data/spec/slacken/filters/elim_blanks_spec.rb +32 -0
- data/spec/slacken/filters/elim_invalid_links_spec.rb +47 -0
- data/spec/slacken/filters/elim_line_breaks_spec.rb +39 -0
- data/spec/slacken/filters/group_indent_spec.rb +35 -0
- data/spec/slacken/filters/group_inlines_spec.rb +31 -0
- data/spec/slacken/filters/sanitize_headline_spec.rb +29 -0
- data/spec/slacken/filters/sanitize_link_spec.rb +23 -0
- data/spec/slacken/filters/sanitize_list_spec.rb +36 -0
- data/spec/slacken/filters/sanitize_table_spec.rb +39 -0
- data/spec/slacken_spec.rb +3 -0
- data/spec/spec_helper.rb +1 -2
- metadata +37 -26
- data/lib/slacken/document_component/elim_blanks.rb +0 -36
- data/lib/slacken/document_component/elim_invalid_links.rb +0 -26
- data/lib/slacken/document_component/elim_line_breaks.rb +0 -27
- data/lib/slacken/document_component/extract_img_alt.rb +0 -12
- data/lib/slacken/document_component/group_indent.rb +0 -27
- data/lib/slacken/document_component/group_inlines.rb +0 -26
- data/lib/slacken/document_component/sanitize_link_containers.rb +0 -40
- data/lib/slacken/document_component/sanitize_special_tag_containers.rb +0 -102
- data/lib/slacken/document_component/stringfy_checkbox.rb +0 -20
- data/lib/slacken/document_component/stringfy_emoji.rb +0 -20
- data/spec/slacken/document_component/elim_blanks_spec.rb +0 -34
- data/spec/slacken/document_component/elim_invalid_links_spec.rb +0 -49
- data/spec/slacken/document_component/elim_line_breaks_spec.rb +0 -41
- data/spec/slacken/document_component/group_indent_spec.rb +0 -37
- data/spec/slacken/document_component/group_inlines_spec.rb +0 -33
- 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
|
data/lib/slacken/node_type.rb
CHANGED
@@ -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?
|
data/lib/slacken/rendering.rb
CHANGED
data/lib/slacken/version.rb
CHANGED
@@ -3,6 +3,6 @@ require 'slacken'
|
|
3
3
|
fixture_dir = File.expand_path('../spec/fixtures', __dir__)
|
4
4
|
|
5
5
|
File.write(
|
6
|
-
File.
|
7
|
-
Slacken.translate(File.read(File.
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|