slacken 0.1.0
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 +7 -0
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +20 -0
- data/README.md +60 -0
- data/Rakefile +36 -0
- data/lib/slacken.rb +21 -0
- data/lib/slacken/document_component.rb +73 -0
- data/lib/slacken/document_component/elim_blanks.rb +36 -0
- data/lib/slacken/document_component/elim_invalid_links.rb +26 -0
- data/lib/slacken/document_component/elim_line_breaks.rb +27 -0
- data/lib/slacken/document_component/extract_img_alt.rb +12 -0
- data/lib/slacken/document_component/group_indent.rb +27 -0
- data/lib/slacken/document_component/group_inlines.rb +26 -0
- data/lib/slacken/document_component/sanitize_link_containers.rb +40 -0
- data/lib/slacken/document_component/sanitize_special_tag_containers.rb +102 -0
- data/lib/slacken/document_component/stringfy_checkbox.rb +20 -0
- data/lib/slacken/document_component/stringfy_emoji.rb +20 -0
- data/lib/slacken/dom_container.rb +45 -0
- data/lib/slacken/node_type.rb +53 -0
- data/lib/slacken/render_element.rb +91 -0
- data/lib/slacken/rendering.rb +102 -0
- data/lib/slacken/slack_url.rb +7 -0
- data/lib/slacken/table_element.rb +23 -0
- data/lib/slacken/version.rb +3 -0
- data/sample/out.txt +38 -0
- data/sample/source.html +55 -0
- data/scripts/update_markup_fixture.rb +8 -0
- data/slacken.gemspec +28 -0
- data/spec/fixtures/example.html +114 -0
- data/spec/fixtures/markup_text.txt +73 -0
- data/spec/helpers/document_component_dsl.rb +11 -0
- data/spec/slacken/document_component/elim_blanks_spec.rb +34 -0
- data/spec/slacken/document_component/elim_invalid_links_spec.rb +49 -0
- data/spec/slacken/document_component/elim_line_breaks_spec.rb +41 -0
- data/spec/slacken/document_component/group_indent_spec.rb +37 -0
- data/spec/slacken/document_component/group_inlines_spec.rb +33 -0
- data/spec/slacken/document_component/sanitize_special_tag_containers_spec.rb +64 -0
- data/spec/slacken/document_component_spec.rb +19 -0
- data/spec/slacken_spec.rb +12 -0
- data/spec/spec_helper.rb +13 -0
- metadata +194 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ffc05a0da1b3b3fc3534666b1de2a36697448557
|
4
|
+
data.tar.gz: 7d0fda248b1f4a64500e5e6e92b3941adc8320ab
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 8ee43ac2dbef90cf74aced8f4e940dde59d80bbbd693fdcc7d822624ea21f51b8a7a13e19345dc9d06cf3363c6c8e1c168e9811f2808484e7f7cc7dfcf0c9067
|
7
|
+
data.tar.gz: 19f4898e6ee95503572ea4bb70005f54d84779f647c93c1c982250685bed83b7f95acf7a4506347f8bc535776e4fd18864edb871bff1f71b071673babde0105d
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format documentation
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2015 Tomoya Chiba
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# slacken
|
2
|
+
|
3
|
+
## Description
|
4
|
+
This gem translates a html source into a markup text for Slack.
|
5
|
+
|
6
|
+
## Examples
|
7
|
+
|
8
|
+
Sample input source and output texts are in `sample/`.
|
9
|
+
|
10
|
+
```
|
11
|
+
> require 'slacken'
|
12
|
+
> puts Slacken.translate(File.read('sample/source.html'))
|
13
|
+
# *Slacken*
|
14
|
+
#
|
15
|
+
# This gem translates a html source into *a markup text for Slack*.
|
16
|
+
# <http://qiita.com|Qiita> uses this gem to decorate notification messages to Slack :trollface:.
|
17
|
+
#
|
18
|
+
# *Examples*
|
19
|
+
#
|
20
|
+
# *List*
|
21
|
+
#
|
22
|
+
# 1. Item 1
|
23
|
+
# 2. _Item 2 (italic)_
|
24
|
+
# • [x] Checked
|
25
|
+
# • [ ] Unchecked
|
26
|
+
# 3. *Item 3 (bold)*
|
27
|
+
# • Nested Item 1
|
28
|
+
# • Nested Item 2
|
29
|
+
#
|
30
|
+
# *Citation*
|
31
|
+
#
|
32
|
+
# > Qiita is a technical information sharing site for programmers.
|
33
|
+
# > Kobito is an application for technical information recording.
|
34
|
+
#
|
35
|
+
# *Source Code*
|
36
|
+
#
|
37
|
+
# ```class World
|
38
|
+
# def hello
|
39
|
+
# puts 'Hello, world!'
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
# ```
|
43
|
+
#
|
44
|
+
# *Image*
|
45
|
+
#
|
46
|
+
# This is a Qiita logo.
|
47
|
+
#
|
48
|
+
# -----------
|
49
|
+
#
|
50
|
+
# <http://cdn.qiita.com/assets/siteid-reverse-1949e989f9d8b2f6fad65a57292b2b01.png|Qiita logo>
|
51
|
+
```
|
52
|
+
|
53
|
+
## Install
|
54
|
+
|
55
|
+
```
|
56
|
+
$ gem install slacken
|
57
|
+
```
|
58
|
+
|
59
|
+
## License
|
60
|
+
MIT
|
data/Rakefile
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
rescue LoadError => e
|
8
|
+
warn e.message
|
9
|
+
warn "Run `gem install bundler` to install Bundler."
|
10
|
+
exit -1
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
Bundler.setup(:development)
|
15
|
+
rescue Bundler::BundlerError => e
|
16
|
+
warn e.message
|
17
|
+
warn "Run `bundle install` to install missing gems."
|
18
|
+
exit e.status_code
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'rake'
|
22
|
+
|
23
|
+
require 'rubygems/tasks'
|
24
|
+
Gem::Tasks.new
|
25
|
+
|
26
|
+
require 'rdoc/task'
|
27
|
+
RDoc::Task.new do |rdoc|
|
28
|
+
rdoc.title = "slacken"
|
29
|
+
end
|
30
|
+
task :doc => :rdoc
|
31
|
+
|
32
|
+
require 'rspec/core/rake_task'
|
33
|
+
RSpec::Core::RakeTask.new
|
34
|
+
|
35
|
+
task :test => :spec
|
36
|
+
task :default => :spec
|
data/lib/slacken.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module Slacken
|
2
|
+
require 'slacken/document_component'
|
3
|
+
require 'slacken/dom_container'
|
4
|
+
require 'slacken/render_element'
|
5
|
+
require 'slacken/rendering'
|
6
|
+
require 'slacken/node_type'
|
7
|
+
require 'slacken/slack_url'
|
8
|
+
require 'slacken/table_element'
|
9
|
+
require 'slacken/version'
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def translate(html_source)
|
13
|
+
convert(html_source).to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def convert(html_source)
|
17
|
+
Slacken::DomContainer.parse_html(html_source)
|
18
|
+
.to_component.to_element
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require 'slacken/document_component/elim_blanks'
|
4
|
+
require 'slacken/document_component/elim_invalid_links'
|
5
|
+
require 'slacken/document_component/elim_line_breaks'
|
6
|
+
require 'slacken/document_component/extract_img_alt'
|
7
|
+
require 'slacken/document_component/group_inlines'
|
8
|
+
require 'slacken/document_component/group_indent'
|
9
|
+
require 'slacken/document_component/sanitize_link_containers'
|
10
|
+
require 'slacken/document_component/sanitize_special_tag_containers'
|
11
|
+
require 'slacken/document_component/stringfy_checkbox'
|
12
|
+
require 'slacken/document_component/stringfy_emoji'
|
13
|
+
|
14
|
+
# Public: An intermediate object that is used when a HTML source is translated into a MarkupElement
|
15
|
+
# representing structure of a markup text.
|
16
|
+
# A DocumentComponent has tree structure and has child nodes as `children`.
|
17
|
+
module Slacken
|
18
|
+
class DocumentComponent
|
19
|
+
include ElimBlanks
|
20
|
+
include ElimInvalidLinks
|
21
|
+
include ElimLineBreaks
|
22
|
+
include ExtractImgAlt
|
23
|
+
include GroupInlines
|
24
|
+
include GroupIndent
|
25
|
+
include SanitizeLinkContainers
|
26
|
+
include SanitizeSpecialTagContainers
|
27
|
+
include StringfyCheckbox
|
28
|
+
include StringfyEmoji
|
29
|
+
|
30
|
+
extend Forwardable
|
31
|
+
def_delegators :@type, :block?, :inline?
|
32
|
+
|
33
|
+
attr_reader :type, :attrs, :children
|
34
|
+
|
35
|
+
def initialize(type, children = [], attrs = {})
|
36
|
+
@type = NodeType.create(type)
|
37
|
+
@attrs = attrs
|
38
|
+
@children = children
|
39
|
+
end
|
40
|
+
|
41
|
+
def derive(new_children, updates = {})
|
42
|
+
self.class.new(
|
43
|
+
updates[:type] || type, new_children, updates[:attrs] || attrs)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Public: Normalize this object's structure and convert it to MarkupElement.
|
47
|
+
def to_element
|
48
|
+
normalize.produce_element
|
49
|
+
end
|
50
|
+
|
51
|
+
def normalize
|
52
|
+
stringfy_emoji
|
53
|
+
.stringfy_checkbox
|
54
|
+
.extract_img_alt
|
55
|
+
.elim_invalid_links
|
56
|
+
.sanitize_link_containers
|
57
|
+
.sanitize_special_tag_containers
|
58
|
+
.group_inlines
|
59
|
+
.group_indent
|
60
|
+
.elim_blanks
|
61
|
+
.elim_line_breaks
|
62
|
+
end
|
63
|
+
|
64
|
+
# Private: Convert this element to a MarkupElement.
|
65
|
+
def produce_element
|
66
|
+
if type.member_of?(:table)
|
67
|
+
TableElement.new(children.map(&:produce_element))
|
68
|
+
else
|
69
|
+
RenderElement.new(type, children.map(&:produce_element), attrs)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
class Slacken::DocumentComponent
|
2
|
+
module ElimBlanks
|
3
|
+
# Private: Reject blank elements
|
4
|
+
def elim_blanks
|
5
|
+
case type.name
|
6
|
+
when :pre
|
7
|
+
self
|
8
|
+
else
|
9
|
+
derive(children.reject(&:blank?).map(&:elim_blanks))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def blank?
|
14
|
+
return @is_blank if !@is_blank.nil?
|
15
|
+
@is_blank =
|
16
|
+
case type.name
|
17
|
+
when :pre, :ul, :li, :br, :hr, :img, :checkbox
|
18
|
+
false
|
19
|
+
when :text, :emoji
|
20
|
+
content = attrs[:content]
|
21
|
+
content.nil? || !content.match(/\A\s*\Z/).nil?
|
22
|
+
else
|
23
|
+
children.empty? || children.all?(&:blank?)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_no_blanks?
|
28
|
+
case type.name
|
29
|
+
when :pre
|
30
|
+
true
|
31
|
+
else
|
32
|
+
!blank? && children.all?(&:has_no_blanks?)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Slacken::DocumentComponent
|
2
|
+
module ElimInvalidLinks
|
3
|
+
# Private: Eliminate internal links and blank links
|
4
|
+
def elim_invalid_links
|
5
|
+
if invalid_link?
|
6
|
+
derive(children.map(&:elim_invalid_links), type: :span)
|
7
|
+
else
|
8
|
+
derive(children.map(&:elim_invalid_links))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def invalid_link?
|
13
|
+
if type.member_of?(:a)
|
14
|
+
link = attrs[:href]
|
15
|
+
link.nil? ||
|
16
|
+
!link.match(%r{\Ahttps?://})
|
17
|
+
else
|
18
|
+
false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def has_no_invalid_links?
|
23
|
+
!invalid_link? && children.all?(&:has_no_invalid_links?)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Slacken::DocumentComponent
|
2
|
+
module ElimLineBreaks
|
3
|
+
# Private: Reject blank elements
|
4
|
+
def elim_line_breaks
|
5
|
+
case type.name
|
6
|
+
when :text
|
7
|
+
new_content = attrs[:content].gsub(/[\r\n]/, '')
|
8
|
+
derive(children, attrs: attrs.merge(content: new_content))
|
9
|
+
when :pre
|
10
|
+
self
|
11
|
+
else
|
12
|
+
derive(children.map(&:elim_line_breaks))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def has_no_line_breaks?
|
17
|
+
case type.name
|
18
|
+
when :text
|
19
|
+
!attrs[:content].match(/[\r\n]/)
|
20
|
+
when :pre
|
21
|
+
true
|
22
|
+
else
|
23
|
+
children.all?(&:has_no_line_breaks?)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class Slacken::DocumentComponent
|
2
|
+
module ExtractImgAlt
|
3
|
+
def extract_img_alt
|
4
|
+
if type.member_of?(:img)
|
5
|
+
child = self.class.new(:text, [], content: attrs[:alt] || attrs[:src])
|
6
|
+
derive([child])
|
7
|
+
else
|
8
|
+
derive(children.map(&:extract_img_alt))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class Slacken::DocumentComponent
|
2
|
+
module GroupIndent
|
3
|
+
# Private: Wrap contents to indent.
|
4
|
+
# Childrens of li or dd tags are wrapped.
|
5
|
+
def group_indent
|
6
|
+
if type.member_of?(:li, :dd)
|
7
|
+
head, *tails = children.map(&:group_indent)
|
8
|
+
derive([head, self.class.new(:indent, tails)])
|
9
|
+
else
|
10
|
+
derive(children.map(&:group_indent))
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def indent_grouped?
|
15
|
+
if type.member_of?(:li, :dd)
|
16
|
+
head, tail = children
|
17
|
+
if tail
|
18
|
+
tail.type.member_of?(:indent) && tail.indent_grouped?
|
19
|
+
else
|
20
|
+
true
|
21
|
+
end
|
22
|
+
else
|
23
|
+
children.all?(&:indent_grouped?)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Slacken::DocumentComponent
|
2
|
+
module GroupInlines
|
3
|
+
# Private: Group inline elements and wrap them in a wrapper node.
|
4
|
+
# Wrapper nodes are introduced to group inline nodes in a paragraph.
|
5
|
+
def group_inlines
|
6
|
+
if block?
|
7
|
+
new_children = children.map(&:group_inlines).chunk(&:inline?).map do |is_inline, group|
|
8
|
+
is_inline ? self.class.new(:wrapper, group) : group
|
9
|
+
end.flatten
|
10
|
+
derive(new_children)
|
11
|
+
else
|
12
|
+
derive(children.map(&:group_inlines))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def inlines_grouped?
|
17
|
+
if type.member_of?(:wrapper)
|
18
|
+
true
|
19
|
+
elsif inline?
|
20
|
+
false
|
21
|
+
else
|
22
|
+
children.all?(&:inlines_grouped?)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Slacken::DocumentComponent
|
2
|
+
module SanitizeLinkContainers
|
3
|
+
# Private: Sanitize not allowed tags in links.
|
4
|
+
def sanitize_link_containers
|
5
|
+
case type.name
|
6
|
+
when :img, :a, :iframe
|
7
|
+
derive(children.map(&:sanitize_in_link))
|
8
|
+
else
|
9
|
+
derive(children.map(&:sanitize_link_containers))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def sanitize_in_link
|
14
|
+
if type.allowed_in_link?
|
15
|
+
derive(children.map(&:sanitize_in_link))
|
16
|
+
else
|
17
|
+
# No block tags are allowed.
|
18
|
+
derive(children.map(&:sanitize_in_link), type: :span)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def link_sanitized?
|
23
|
+
case type.name
|
24
|
+
when :img, :a, :iframe
|
25
|
+
children.all?(&:list_containers_sanitized?)
|
26
|
+
else
|
27
|
+
children.all?(&:link_sanitized?)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def link_container_sanitized?
|
32
|
+
if type.allowed_in_link?
|
33
|
+
children.all?(&:link_containers_sanitized?)
|
34
|
+
else
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
class Slacken::DocumentComponent
|
2
|
+
module SanitizeSpecialTagContainers
|
3
|
+
# Private: Sanitize not allowed tags in list, headline, and table.
|
4
|
+
def sanitize_special_tag_containers
|
5
|
+
# NOTE: each special tag (list, headline, and table) is not allowed to occur
|
6
|
+
# in another type special tags.
|
7
|
+
case type.name
|
8
|
+
when /h\d/
|
9
|
+
derive(children.map(&:sanitize_headline))
|
10
|
+
when :ul, :ol, :dl
|
11
|
+
derive(children.map(&:sanitize_list))
|
12
|
+
when :table
|
13
|
+
derive(children.map(&:sanitize_table))
|
14
|
+
else
|
15
|
+
derive(children.map(&:sanitize_special_tag_containers))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def sanitize_headline
|
20
|
+
if type.allowed_in_headline?
|
21
|
+
derive(children.map(&:sanitize_headline))
|
22
|
+
else
|
23
|
+
# No block tags are allowed.
|
24
|
+
derive(children.map(&:sanitize_headline), type: :span)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def sanitize_list
|
29
|
+
if type.member_of?(:li, :dd)
|
30
|
+
head, *tails = children
|
31
|
+
derive([head.sanitize_list_item, *tails.map(&:sanitize_list)])
|
32
|
+
elsif type.allowed_in_list?
|
33
|
+
derive(children.map(&:sanitize_list))
|
34
|
+
else
|
35
|
+
derive(children.map(&:sanitize_list), type: block? ? :div : :span)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def sanitize_list_item
|
40
|
+
if type.allowed_as_list_item?
|
41
|
+
derive(children.map(&:sanitize_list_item))
|
42
|
+
else
|
43
|
+
# No block tags are allowed.
|
44
|
+
derive(children.map(&:sanitize_list_item), type: :span)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def sanitize_table
|
49
|
+
if type.allowed_in_table?
|
50
|
+
derive(children.map(&:sanitize_table))
|
51
|
+
else
|
52
|
+
# No block tags are allowed.
|
53
|
+
derive(children.map(&:sanitize_table), type: :span)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def sanitized?
|
58
|
+
case type.name
|
59
|
+
when /h\d/
|
60
|
+
children.all?(&:headline_sanitized?)
|
61
|
+
when :ul, :ol, :dl
|
62
|
+
children.all?(&:list_sanitized?)
|
63
|
+
when :table
|
64
|
+
children.all?(&:table_sanitized?)
|
65
|
+
else
|
66
|
+
children.all?(&:sanitized?)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def headline_sanitized?
|
71
|
+
if type.allowed_in_headline?
|
72
|
+
children.all?(&:headline_sanitized?)
|
73
|
+
else
|
74
|
+
false
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def list_sanitized?
|
79
|
+
if type.allowed_in_list?
|
80
|
+
children.all?(&:list_sanitized?)
|
81
|
+
else
|
82
|
+
false
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def list_item_sanitized?
|
87
|
+
if type.allowed_as_list_item?
|
88
|
+
children.all?(&:list_item_sanitized?)
|
89
|
+
else
|
90
|
+
false
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def table_sanitized?
|
95
|
+
if type.allowed_in_table?
|
96
|
+
children.all?(&:table_sanitized?)
|
97
|
+
else
|
98
|
+
false
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|