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